Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to persist when using Spring Boot with JPA

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 ...

@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.

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.

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.

I have an Application class that bootstraps the 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

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?

like image 662
Jan Vladimir Mostert Avatar asked Mar 10 '16 20:03

Jan Vladimir Mostert


2 Answers

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

I think what you may be looking for are Spring Data Repositories. I would recommend reading that to get the basics.

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.

Inside of your Application class you can add the @EnableJpaRepositories annotation.

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

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

Where Account is the type of Entity and Long is the ID type of Account

There are a few repository interfaces with various support included with Spring Data that inherit from Repository.

Without adding anything to your interface, PagingAndSortingRepository will give you support CRUD operations and paging.

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

Now, you can @Autowire AccountRepository into any of your Spring managed beans and begin saving and fetching data.

like image 140
francis Avatar answered Sep 20 '22 12:09

francis


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.

like image 44
Griff Avatar answered Sep 18 '22 12:09

Griff