About
How to model a many-to-many relationship in JPA.
Articles Related
Data Model
(Oracle) Database
One Hello can have several Category and One Category can have several Hello.
The Ddl File: Ddl File
One sequence:
CREATE SEQUENCE "SEQ_GEN_IDENTITY" MINVALUE 1 MAXVALUE
9999999999999999999999999999 INCREMENT BY 1 START WITH 1;
JPA
Hello Table with the HelloCategory Table
The HelloWorld entity with an object-relational mapping annotation that models the HELLO and HELLOCATEGORIE tables.
import javax.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "HELLO")
public class HelloWorld implements Serializable {
@Id
@Column(name = "ID", unique = true, nullable = false, updatable=false)
private String id;
@Basic()
@Column(name = "DESCRIPTION")
private String Description;
// The Many-to-May Column is declared here
@ManyToMany
@JoinTable(name = "HELLOCATEGORIE", joinColumns = @JoinColumn(name = "ID_HELLO"), inverseJoinColumns = @JoinColumn(name = "ID_CAT"))
private List<HelloCategory> helloCategories = new ArrayList<HelloCategory>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDescription() {
return Description;
}
public void setDescription(String description) {
Description = description;
}
public void add(HelloCategory helloCategory) {
//To change body of created methods use File | Settings | File Templates.
getHelloCategories().add(helloCategory);
}
public List<HelloCategory> getHelloCategories() {
return helloCategories;
}
@Override
public String toString() {
return "HelloWorld{" +
"id='" + id + '\'' +
", Description='" + Description + '\'' +
", helloCategories=" + helloCategories +
'}';
}
}
Category Table
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Table(name="CAT")
public class HelloCategory implements Serializable {
@Id
@Column(name = "ID_CAT")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Basic
@Column(name = "CAT_NAME")
private String title;
public HelloCategory() {
}
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public String toString() {
return "HelloCategory{" +
"id=" + id +
", title='" + title + '\'' +
'}';
}
}
Persistence Unit Configuration
The persistence unit (PersistenceUnitName) in the persistence.xml file that defines:
- all entities
- and the eclipselink persistence provider
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="PersistenceUnitName" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>HelloWorld</class>
<class>HelloCategory</class>
</persistence-unit>
</persistence>
Main Code
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.config.TargetDatabase;
import org.eclipse.persistence.logging.SessionLog;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map props = new HashMap();
props.put(PersistenceUnitProperties.JDBC_USER, "sh");
props.put(PersistenceUnitProperties.JDBC_PASSWORD, "sh");
props.put(PersistenceUnitProperties.TARGET_DATABASE, TargetDatabase.Oracle11);
props.put(PersistenceUnitProperties.JDBC_DRIVER,"oracle.jdbc.OracleDriver");
props.put(PersistenceUnitProperties.JDBC_URL,"jdbc:oracle:thin:@localhost:1521/pdborcl.hotitem.local");
props.put(PersistenceUnitProperties.LOGGING_LEVEL, SessionLog.FINE_LABEL);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PersistenceUnitName", props);
EntityManager em = emf.createEntityManager();
// A normal Hello World Construction
// The normal Hello World
HelloWorld aNormalHelloWorld = new HelloWorld();
aNormalHelloWorld.setId("1");
aNormalHelloWorld.setDescription("Hello Nico !");
// The normal Hello Categorie
HelloCategory aNormalHelloCategory = new HelloCategory();
aNormalHelloCategory.setTitle("A normal Hello");
aNormalHelloWorld.add(aNormalHelloCategory);
// A Big Hello World Construction
// The big Hello
HelloWorld aBigHelloWorld = new HelloWorld();
aBigHelloWorld.setId("2");
aBigHelloWorld.setDescription("HELLO NICO !");
// The big Category
HelloCategory aBigHelloCategory = new HelloCategory();
aBigHelloCategory.setTitle("A BIG Hello");
aBigHelloWorld.add(aBigHelloCategory);
// Persistence
em.getTransaction().begin();
em.merge(aNormalHelloWorld);
em.merge(aBigHelloWorld);
em.getTransaction().commit();
// Retrieve
// Hello World whose primary key is 1
HelloWorld helloWorld = em.find(HelloWorld.class, "1");
System.out.println(helloWorld);
em.close();
emf.close();
}
}
Output
Jpa Eclipselink Log:
[EL Config]: metadata: 2013-12-21 17:22:38.189--ServerSession(1595026786)--Thread(Thread[main,5,main])--The access type for the persistent class [class HelloCategory] is set to [FIELD].
[EL Config]: metadata: 2013-12-21 17:22:38.22--ServerSession(1595026786)--Thread(Thread[main,5,main])--The access type for the persistent class [class HelloWorld] is set to [FIELD].
[EL Config]: metadata: 2013-12-21 17:22:38.234--ServerSession(1595026786)--Thread(Thread[main,5,main])--The target entity (reference) class for the many to many mapping element [field helloCategories] is being defaulted to: class HelloCategory.
[EL Config]: metadata: 2013-12-21 17:22:38.235--ServerSession(1595026786)--Thread(Thread[main,5,main])--The alias name for the entity class [class HelloCategory] is being defaulted to: HelloCategory.
[EL Config]: metadata: 2013-12-21 17:22:38.267--ServerSession(1595026786)--Thread(Thread[main,5,main])--The alias name for the entity class [class HelloWorld] is being defaulted to: HelloWorld.
[EL Config]: metadata: 2013-12-21 17:22:38.294--ServerSession(1595026786)--Thread(Thread[main,5,main])--The source primary key column name for the many to many mapping [field helloCategories] is being defaulted to: ID.
[EL Config]: metadata: 2013-12-21 17:22:38.295--ServerSession(1595026786)--Thread(Thread[main,5,main])--The target primary key column name for the many to many mapping [field helloCategories] is being defaulted to: ID_CAT.
[EL Info]: 2013-12-21 17:22:38.962--ServerSession(1595026786)--Thread(Thread[main,5,main])--EclipseLink, version: Eclipse Persistence Services - 2.5.2.v20131113-a7346c6
[EL Config]: connection: 2013-12-21 17:22:38.971--ServerSession(1595026786)--Connection(1297590473)--Thread(Thread[main,5,main])--connecting(DatabaseLogin(
platform=>Oracle11Platform
user name=> "sh"
datasource URL=> "jdbc:oracle:thin:@localhost:1521/pdborcl.hotitem.local"
))
[EL Config]: connection: 2013-12-21 17:22:39.503--ServerSession(1595026786)--Connection(3559837)--Thread(Thread[main,5,main])--Connected: jdbc:oracle:thin:@localhost:1521/pdborcl.hotitem.local
User: SH
Database: Oracle Version: Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
Driver: Oracle JDBC driver Version: 11.1.0.7.0-Production
[EL Info]: connection: 2013-12-21 17:22:39.576--ServerSession(1595026786)--Thread(Thread[main,5,main])--file:/D:/svn_obiee-utility-plus/target/classes/_PersistenceUnitName_url=jdbc:oracle:thin:@localhost:1521/pdborcl.hotitem.local_user=sh login successful
[EL Fine]: sql: 2013-12-21 17:22:39.64--ServerSession(1595026786)--Connection(3559837)--Thread(Thread[main,5,main])--SELECT ID, DESCRIPTION FROM HELLO WHERE (ID = ?)
bind => [1]
[EL Fine]: sql: 2013-12-21 17:22:39.775--ServerSession(1595026786)--Connection(3559837)--Thread(Thread[main,5,main])--SELECT t1.ID_CAT, t1.CAT_NAME FROM HELLOCATEGORIE t0, CAT t1 WHERE ((t0.ID_HELLO = ?) AND (t1.ID_CAT = t0.ID_CAT))
bind => [1]
[EL Fine]: sql: 2013-12-21 17:22:39.781--ServerSession(1595026786)--Connection(3559837)--Thread(Thread[main,5,main])--SELECT SEQ_GEN_IDENTITY.NEXTVAL FROM DUAL
[EL Fine]: sql: 2013-12-21 17:22:39.783--ServerSession(1595026786)--Connection(3559837)--Thread(Thread[main,5,main])--SELECT ID, DESCRIPTION FROM HELLO WHERE (ID = ?)
bind => [2]
[EL Fine]: sql: 2013-12-21 17:22:39.785--ServerSession(1595026786)--Connection(3559837)--Thread(Thread[main,5,main])--SELECT t1.ID_CAT, t1.CAT_NAME FROM HELLOCATEGORIE t0, CAT t1 WHERE ((t0.ID_HELLO = ?) AND (t1.ID_CAT = t0.ID_CAT))
bind => [2]
[EL Fine]: sql: 2013-12-21 17:22:39.787--ServerSession(1595026786)--Connection(3559837)--Thread(Thread[main,5,main])--SELECT SEQ_GEN_IDENTITY.NEXTVAL FROM DUAL
[EL Fine]: sql: 2013-12-21 17:22:39.796--ClientSession(1269220824)--Connection(3559837)--Thread(Thread[main,5,main])--INSERT INTO CAT (ID_CAT, CAT_NAME) VALUES (?, ?)
bind => [34, A BIG Hello]
[EL Fine]: sql: 2013-12-21 17:22:39.798--ClientSession(1269220824)--Connection(3559837)--Thread(Thread[main,5,main])--INSERT INTO CAT (ID_CAT, CAT_NAME) VALUES (?, ?)
bind => [33, A normal Hello]
[EL Fine]: sql: 2013-12-21 17:22:39.801--ClientSession(1269220824)--Connection(3559837)--Thread(Thread[main,5,main])--DELETE FROM HELLOCATEGORIE WHERE ((ID_CAT = ?) AND (ID_HELLO = ?))
bind => [31, 1]
[EL Fine]: sql: 2013-12-21 17:22:39.804--ClientSession(1269220824)--Connection(3559837)--Thread(Thread[main,5,main])--INSERT INTO HELLOCATEGORIE (ID_CAT, ID_HELLO) VALUES (?, ?)
bind => [33, 1]
[EL Fine]: sql: 2013-12-21 17:22:39.805--ClientSession(1269220824)--Connection(3559837)--Thread(Thread[main,5,main])--DELETE FROM HELLOCATEGORIE WHERE ((ID_CAT = ?) AND (ID_HELLO = ?))
bind => [32, 2]
[EL Fine]: sql: 2013-12-21 17:22:39.807--ClientSession(1269220824)--Connection(3559837)--Thread(Thread[main,5,main])--INSERT INTO HELLOCATEGORIE (ID_CAT, ID_HELLO) VALUES (?, ?)
bind => [34, 2]
System Output
HelloWorld{id='1', Description='Hello Nico !', helloCategories={[HelloCategory{id=33, title='A normal Hello'}]}}
Remaining Jpa Eclipselink Log
[EL Config]: connection: 2013-12-21 17:22:39.819--ServerSession(1595026786)--Connection(3559837)--Thread(Thread[main,5,main])--disconnect
[EL Info]: connection: 2013-12-21 17:22:39.82--ServerSession(1595026786)--Thread(Thread[main,5,main])--file:/D:/svn_obiee-utility-plus/target/classes/_PersistenceUnitName_url=jdbc:oracle:thin:@localhost:1521/pdborcl.hotitem.local_user=sh logout successful
[EL Config]: connection: 2013-12-21 17:22:39.821--ServerSession(1595026786)--Connection(1297590473)--Thread(Thread[main,5,main])--disconnect