在@PostConstruct的春季启动中使用普通EntityManager持久化JPA实体

时间:2019-06-17 15:02:55

标签: java spring-boot jpa entitymanager spring-transactions

我有一个最小的spring boot应用程序,它由3个类组成:一个Entity,一个试图在@PostConstruct中填充db的组件和一个应用程序类。没什么。

@SpringBootApplication
public class App {
  public static void main(String[] args) {
    SpringApplication.run(App.class, args);
  }
}

@Component
@Transactional
public class Initializer {
    @Autowired
    EntityManager em;

    @PostConstruct
    public void populate() {
        em.persist(new MyEntity());
    }
}

@Entity
public class MyEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    int id;
}

当我运行应用程序时,我得到一个javax.persistence.TransactionRequiredException:没有用于当前线程的具有实际事务的EntityManager-无法可靠地处理“持久”调用

我不是唯一一个遇到此错误的人,我阅读了很多帖子,但没有找到一个神奇的解决方案。

如果我自动连接EntityMananagerFactory而改为:

EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(new MyEntity());
em.getTransaction().commit();
em.close();

有效。问题是:是否有一种更简单的方法(在正确的位置放置正确的注释)来获得可以保留实体的EntityManager?我有充分的理由不创建存储库(我尝试这样做是可行的)。

最诚挚的Jens

2 个答案:

答案 0 :(得分:0)

据我了解,当我们要初始化bean和配置时,@ PostConstruct在应用启动时被调用。我认为@PostConstruct不是这样做的正确地方。

但是,您可以在EntityManger上使用@PersistenceContext,而不是自动装配。

答案 1 :(得分:0)

因此,在尝试了很多不同的东西之后,我认为我找到了一个可行的解决方案,其中初始化是在ApplicationReadyEvent处理程序中而不是在@PostConstruct方法中完成的:

@Component
public class Initializer {

    @PersistenceContext
    EntityManager em;

    @EventListener(ApplicationReadyEvent.class)
    @Transactional
    public void init() {
        em.persist(new MyEntity());
    }
}

工作示例:https://github.com/djarnis73/spring-boot-db-init-with-jpa-entity-manager