Java 使用带有 JPA 的 Spring Boot 时如何坚持
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35926935/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to persist when using Spring Boot with JPA
提问by Jan Vladimir Mostert
I'm used to using Spring Roo to generate my entities and having it handle injecting the entityManager as well as the persist and other methods via AspectJ classes. Now I'm trying to use Spring Boot to do something simple that will write things to the database ...
我习惯于使用 Spring Roo 来生成我的实体,并让它通过 AspectJ 类处理注入 entityManager 以及持久化和其他方法。现在我正在尝试使用 Spring Boot 做一些简单的事情,将内容写入数据库......
@Entity
@Table(name = "account")
public class Account {
transient EntityManager entityManager;
@Id
@GeneratedValue
private Long id;
@Column(name = "username", nullable = false, unique = true)
private String username;
@Column(name = "password", nullable = false)
private String password;
... getters and setters
@Transactional
public void persist() {
if (this.entityManager == null) this.entityManager = entityManager();
this.entityManager.persist(this);
}
@Transactional
public Account merge() {
if (this.entityManager == null) this.entityManager = entityManager();
Account merged = this.entityManager.merge(this);
this.entityManager.flush();
return merged;
}
When I'm calling persist or merge, entityManager is obviously null.
当我调用persist 或merge 时,entityManager 显然是空的。
I've also tried adding implements CrudRepository<Account, Long>
to the Account
class to see it'll give me that functionality via a Default Implementation, but what I'm getting is simply empty classes that needs to be filled in.
我还尝试添加implements CrudRepository<Account, Long>
到Account
类中,以查看它会通过默认实现为我提供该功能,但我得到的只是需要填充的空类。
I've had a look at the Spring Boot docs, they cover it very briefly omitting just enough detail to so that it's not obvious what I'm missing.
我看过 Spring Boot 文档,他们非常简短地介绍了它,省略了足够的细节,因此我遗漏的内容并不明显。
I have an Application class that bootstraps the application:
我有一个引导应用程序的 Application 类:
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
My properties file looks like this:
我的属性文件如下所示:
spring.application.name: Test Application
spring.datasource.url: jdbc:mysql://localhost/test
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
This database is automatically being created thanks to the ddl-auto=update
property
由于该ddl-auto=update
属性,该数据库正在自动创建
What is the correct way to persist entities in Spring Boot + JPA and if what I've done is correct so far, how do I "autowire" or auto-create the entityManager?
在 Spring Boot + JPA 中保留实体的正确方法是什么,如果到目前为止我所做的都是正确的,我如何“自动装配”或自动创建实体管理器?
采纳答案by francis
In your example your EntityManager
is always going to be null. Spring will not automatically wire one into your Entity
class. I'm also not sure what your goal is here but I'm willing to bet you most likely don't want to have your Entity
hold your EntityManager
在您的示例中,您EntityManager
将始终为空。Spring 不会自动将一个连接到您的Entity
类中。我也不确定你在这里的目标是什么,但我敢打赌你很可能不想让你Entity
的EntityManager
I think what you may be looking for are Spring Data Repositories. I would recommend reading that to get the basics.
我认为您可能正在寻找的是Spring Data Repositories。我建议阅读它以获得基础知识。
To get started with repositories:
要开始使用存储库:
First thing I would do would be remove transient EntityManager entityManager;
and your persist/merge
functions from your Account
class.
我要做的第一件事就是从你的班级中删除transient EntityManager entityManager;
你的persist/merge
功能Account
。
Inside of your Application
class you can add the @EnableJpaRepositories
annotation.
在您的Application
课程中,您可以添加@EnableJpaRepositories
注释。
Next create a new Interface
(not a new class), this will be your Account
repository.
接下来创建一个新的Interface
(不是一个新的类),这将是你的Account
存储库。
@Repository
public interface AccountRepository extends PagingAndSortingRepository<Account, Long>
Where Account
is the type of Entity
and Long
is the ID type of Account
哪里Account
是类型Entity
和Long
是的ID类型Account
There are a few repository interfaces with various support included with Spring Data that inherit from Repository
.
Spring Data 中包含一些具有各种支持的存储库接口,它们继承自Repository
.
Without adding anything to your interface, PagingAndSortingRepository
will give you support CRUD operations and paging.
无需向您的界面添加任何内容,即可PagingAndSortingRepository
支持 CRUD 操作和分页。
Its also possible to add custom queries to your interface using JPQL, take a look at the @Query
annotation. http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query
也可以使用 JPQL 向您的界面添加自定义查询,请查看@Query
注释。http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query
Now, you can @Autowire
AccountRepository
into any of your Spring managed beans and begin saving and fetching data.
现在,您可以@Autowire
AccountRepository
进入任何 Spring 托管 bean 并开始保存和获取数据。
回答by Griff
Try replacing:
尝试更换:
@Configuration
@ComponentScan
@EnableAutoConfiguration
with:
和:
@SpringBootApplication
See this article
看这篇文章
Specifically: By default, Spring Boot will enable JPA repository support and look in the package (and its subpackages) where @SpringBootApplication is located. If your configuration has JPA repository interface definitions located in a package not visible, you can point out alternate packages using @EnableJpaRepositories and its type-safe basePackageClasses=MyRepository.class parameter.
具体来说:默认情况下,Spring Boot 将启用 JPA 存储库支持并查看 @SpringBootApplication 所在的包(及其子包)。如果您的配置具有位于不可见包中的 JPA 存储库接口定义,您可以使用 @EnableJpaRepositories 及其类型安全的 basePackageClasses=MyRepository.class 参数指出备用包。
回答by Valerio Vaudi
the problem in your code was:
您的代码中的问题是:
- EntityManager entry was not @Autowired and even if it was @Entity isn't recognized as a spring bean and for this reason the dependency injection service of spring didn't work
- since that how i said previously the bean annotated with @Entity isn't a spring bean and for this reason you can't benefit of @Transactional annotation
- EntityManager 条目不是@Autowired,即使是@Entity 也不会被识别为spring bean,因此spring 的依赖注入服务不起作用
- 因为我之前说过用@Entity 注释的bean 不是spring bean,因此您无法从@Transactional 注释中受益
You can use Spring DataJPA project in this case remember of configure tis with @EnableJpaRepositories or you can create the your repository organizing your code in this way
在这种情况下,您可以使用 Spring DataJPA 项目,请记住使用 @EnableJpaRepositories 配置 tis,或者您可以创建以这种方式组织代码的存储库
Entity:
实体:
@Entity
@Table(name = "account")
public class Account {
@Id
@GeneratedValue
private Long id;
@Column(name = "username", nullable = false, unique = true)
private String username;
@Column(name = "password", nullable = false)
private String password;
....
}
}
Repository layer:
存储层:
public interface AccountRepository {
void persist();
Account merge();
}
@Repository
class AccountRepositoryJpaImpl implements AccountRepository {
@Autowired
private EntityManager entityManager;
...
@Transactional
public void persist() {
if (this.entityManager == null) this.entityManager = entityManager();
this.entityManager.persist(this);
}
@Transactional
public Account merge() {
if (this.entityManager == null) this.entityManager = entityManager();
Account merged = this.entityManager.merge(this);
this.entityManager.flush();
return merged;
}
....
}
@SpringBootApplication for benefit of all feature of spring boot @EnableTransactionManagement for benefit of Transaction management
@SpringBootApplication 用于 Spring Boot 的所有功能的好处 @EnableTransactionManagement 用于事务管理的好处
@SpringBootApplication
@EnableTransactionManagement
class ApplicationConfig {
public static void main(String[] args) {
SpringApplication.run(ApplicationConfig .class, args);
}
}
I hope that this can help you. (Spelling corrected 2018-02-24)
我希望这可以帮助你。(拼写更正 2018-02-24)