JPA - MerajAhmadAnsari/self Wiki

DB Integration

Spring Boot JPA base/core dependency

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

Spring boot PostgreSQL DB integration

  1. Add dependency in pom.xml-
        <dependency>
            <artifactId>postgresql</artifactId>
            <groupId>org.postgresql</groupId>
        </dependency>
  1. Add DB connection properties-
    spring.datasource.url=jdbc:postgresql://localhost:5432/authservice
    spring.datasource.username=postgres
    spring.datasource.password=initpw#00
  1. Add Hibernate properties-
    spring.jpa.hibernate.ddl-auto=update
    spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

Spring boot H2 DB integration

  1. Add dependency in pom.xml-
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
  1. Enable H2-Console Add following in application***.properties file-
    spring.h2.console.enabled=true
  1. H2 DB setting There is no need to provide additional setting except dependency in pom.xml but there is option to customize DB setting-
   spring.datasource.url=jdbc:h2:<mem/file>:<InMemory DB name/Persistence DB name>
   spring.datasource.driverClassName=org.h2.Driver
   spring.datasource.username=sa
   spring.datasource.password=
  1. Enable remote H2 Console access if deployed in Tomcat
spring.h2.console.settings.web-allow-others=true
  1. Add Hibernate property If needed then add -
    spring.jpa.hibernate.ddl-auto=create
    spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

JPA Relationships

GenerationType

  1. GenerationType.AUTO
  1. GenerationType.IDENTITY
  1. GenerationType.SEQUENCE
  1. GenerationType.TABLE
DB name AUTO IDENTITY SEQUENCE Table
Oracle --- No Yes
PostgreSQL --- Yes Yes
MySQL --- Yes Yes
SQL Server --- Yes --
H2 --- Yes ---

Mapping

One to One mapping

There are 3 ways to handle 1-1 mapping-

  1. Using a foreign key-

1-1 mapping image

Lets consider the relation ship between user and address. A user can have 1 address. An address can be a independent entity but a user can not exist without address. So that means user is owning address entity.

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "address_id", referencedColumnName = "id")
    private Address address;
    @OneToOne(mappedBy = "address")
    private User user;

**Problem ** with this approach is to use one unwanted foreign key reference column in owning entity

  1. Using a shared Primary key-

1-1 mapping image

Instead of creating new "address_id" column in owning entity, mark primary key of non owning entity as foreign key of owning entity.

    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
    `private Address address;
   public class Address { 
   @Id
   @Column(name = "id")
   private Long id;
    @OneToOne
    @MapsId
    private User user;
  1. Using a join table- This depicts non mandatory relationship. Think about user and workstation entity where an user can have/have not workstation and vice versa.

1-1 mapping image

Use Join table to depict optional 1-1 relationship.

    @OneToOne(cascade = CascadeType.ALL)`
    @JoinTable(name = "emp_workstation", `
      joinColumns = 
        { @JoinColumn(name = "employee_id", referencedColumnName = "id") },
          inverseJoinColumns = 
        { @JoinColumn(name = "workstation_id", referencedColumnName = "id") })
    private WorkStation workStation;
    @OneToOne(mappedBy = "workStation")
    private Employee employee;

One to many mapping

  1. Unidirectional Many to One
@Entiry
public class OrdeItem{

@ManyToOne
private Order order;//Note-1/2
--------------------
--------------------
}

Note 1 - By default Hibernate will create foreign key relation ship based on _ So hibernate will create a new column "order_id" representing as the foreign key relationship

Note 2 - In case custom foreign key column name instead of "order_id", use @JoinColumn(name = ""). e.g. -

@Entiry
public class OrdeItem{
@ManyToOne
@JoinColumn(name = "fk_order")
private Order order;
……………………………………………………………………………………
……………………………………………………………………………………
}
Order o = em.find(Order.class, 1L); 
OrderItem i = new OrderItem();
i.setOrder(o); 
em.persist(i);
  1. Unidirectional One to Many
@Entity
public class Order {
 
    @OneToMany
    @JoinColumn(name = “fk_order_item”)
    private List<OrderItem> items = new ArrayList<OrderItem>();
    ……………………………………………………………………………………
    ……………………………………………………………………………………
}
Order o = em.find(Order.class, 1L); 
OrderItem i = new OrderItem(); 
o.getItems().add(i); 
em.persist(i);
  1. Bi-directional One to Many
@Entity
public class OrderItem {
     @ManyToOne
    @JoinColumn(name = “fk_order”)
    private Order order;
     …
}
@Entity
public class Order { 
    @OneToMany(mappedBy = “order”)
    private List<OrderItem> items = new ArrayList<OrderItem>(); 
    …
}
Order o = em.find(Order.class, 1L); 
OrderItem i = new OrderItem();
i.setOrder(o); 
o.getItems().add(i); 
em.persist(i);

Many to many mapping

Classified in following categories-

  1. Uni-directional many to many associations
@Entity
public class Store{

@ManyToMany
@JoinTable(name = “store_product”,
           joinColumns = { @JoinColumn(name = “fk_store”) },
           inverseJoinColumns = { @JoinColumn(name = “fk_product”) })
  private Set<Product> product;
..................
..................
}
Store s = em.find(Store.class, 1L); 
Product p = new Product(); 
s.getProducts().add(p); 
em.persist(p);
  1. Bi-directional many to many associations
@Entity
public class Store { 
    @ManyToMany
    @JoinTable(name = “store_product”,
           joinColumns = { @JoinColumn(name = “fk_store”) },
           inverseJoinColumns = { @JoinColumn(name = “fk_product”) })
    private Set<Product> products = new HashSet<Product>();
     …
}
@Entity
public class Product{
     @ManyToMany(mappedBy=”products”)
    private Set<Store> stores = new HashSet<Store>();
     …
}

Javax validation framework

        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>

Entity validation

 @Column(name = "mobile_number", nullable = false)
 String mobileNumber;

Generic JPA/DB tricks

ALTER TABLE <Table_name> ALTER COLUMN <column name> VARCHAR (255);
    @NotNull
    @Enumerated(EnumType.STRING)
    eOrderAction nextAction;

References

http://dolszewski.com/java/save-enum-database-jpa/