1

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

4
  • 1
    Spring transactional management is the easy way. However, that does not make a transaction available in a PostConstruct method. Trying to initialize data in such a method is simply the wrong way to go about it. You initialize the bean in such a method, not a database. Commented Jun 17, 2019 at 15:11
  • This might be helpful: stackoverflow.com/questions/17346679/… Commented Jun 17, 2019 at 15:40
  • Thanks @MaximMarkov, that helped me solve my problem, will post a working solution shortly. Commented Jun 18, 2019 at 7:52
  • @Gimby is there a right way for initializing database on application startup (perhaps an @EventListener)? I remember researching how to programatically initialize/populate the database on application startup a while ago without finding any best-practice. Commented Jun 18, 2019 at 9:14

2 Answers 2

2

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

Sign up to request clarification or add additional context in comments.

Comments

0

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.

1 Comment

Yes, I have seen the several pointers about not having transactions in @PostConstruct/InitializingBean. You do have them if you use a Repository instead of an EntityManager, which I guess is what confused me. I did try with @PersistenceContext and did not see any difference in behaviour.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.