简体   繁体   中英

Persisting JPA entity using plain EntityManager in spring boot in @PostConstruct

I have a minimal spring boot application, consisting of 3 classes: an Entity, a component that tries to populate db in @PostConstruct and an application class. Nothing else.

@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;
}

When I run the application I get an javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call

I'm not the only one ever getting that error and I read a lot of the posts, but did not find a magic solution.

If I autowire an EntityMananagerFactory and instead do:

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

It works. Question is: Is there a simpler way (place the right annotation at the right spot) to get an EntityManager that can persist an entity? I have good reasons for not creating a repository (I tried doing that and that works).

Best regards Jens

As per my understanding, @PostConstruct gets called on app startup when we want to initialize the beans and the configs. I think @PostConstruct is not the right place to do so.

However you can use @PersistenceContext on your entityManger instead of autowiring it.

So after trying a lot of different stuff, I think that I found a working solution, where the initalization is done in an ApplicationReadyEvent handler instead of in a @PostConstruct method:

@Component
public class Initializer {

    @PersistenceContext
    EntityManager em;

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

Working example: https://github.com/djarnis73/spring-boot-db-init-with-jpa-entity-manager

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM