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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 17:15:43  来源:igfitidea点击:

How to persist when using Spring Boot with JPA

javaspringjpaspring-bootspring-data

提问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 Accountclass 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=updateproperty

由于该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 EntityManageris always going to be null. Spring will not automatically wire one into your Entityclass. 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 Entityhold your EntityManager

在您的示例中,您EntityManager将始终为空。Spring 不会自动将一个连接到您的Entity类中。我也不确定你在这里的目标是什么,但我敢打赌你很可能不想让你EntityEntityManager

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/mergefunctions from your Accountclass.

我要做的第一件事就是从你的班级中删除transient EntityManager entityManager;你的persist/merge功能Account

Inside of your Applicationclass you can add the @EnableJpaRepositoriesannotation.

在您的Application课程中,您可以添加@EnableJpaRepositories注释。

Next create a new Interface(not a new class), this will be your Accountrepository.

接下来创建一个新的Interface(不是一个新的类),这将是你的Account存储库。

@Repository
public interface AccountRepository extends PagingAndSortingRepository<Account, Long>

Where Accountis the type of Entityand Longis the ID type of Account

哪里Account是类型EntityLong是的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, PagingAndSortingRepositorywill 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 @Queryannotation. 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 @AutowireAccountRepositoryinto any of your Spring managed beans and begin saving and fetching data.

现在,您可以@AutowireAccountRepository进入任何 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:

您的代码中的问题是:

  1. 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
  2. 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
  1. EntityManager 条目不是@Autowired,即使是@Entity 也不会被识别为spring bean,因此spring 的依赖注入服务不起作用
  2. 因为我之前说过用@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)