jpa - 如何创建与 IdClass 的多对多关系?
jpa - How to create a many to many relationship with an IdClass?
我有 3 个 table 具有多对多关系
- 一个(id,name,....)主键id
- B (id, name, ....) with primary key id
- AB (id_a, id_b, date, ....) - table 与 no 的关系
主键
我可以为休眠建模 类 以便我使用 IdClass 而不是 EmbeddedId 解决方案(这样我就可以避免使用级联不必要的级别进行调用 - getId().getA())
PS 尝试混合使用这些解决方案,但没有成功:
http://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/
How to map a composite key with Hibernate?
When it comes to building relationships between entities,
the closest wall next to me and my head often join... (Stephan)
下面是实体 A 和 B 之间多对多关系的工作示例:
A.java
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class A {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Column(name="id_a")
private Integer id;
private String name;
@OneToMany(mappedBy="a",cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private List<AB> abAssociations = new ArrayList<>();
// Getters and setters...
}
B.java
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class B {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Column(name = "id_b")
private Integer id;
private String name;
@OneToMany(mappedBy = "b", cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private List<AB> abAssociations = new ArrayList<>();
// Getters and setters...
}
AB.java
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@Entity
@IdClass(ABid.class)
public class AB {
@Id
@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private A a;
@Id
@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private B b;
@Temporal(TemporalType.TIMESTAMP)
private Date date;
// Getters and setters...
}
ABid.java
import java.io.Serializable;
// The IdClass MUST implement Serializable and override #hashCode and #equals
public class ABid implements Serializable {
private static final long serialVersionUID = -2834827403836993112L;
private A a;
private B b;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((a == null) ? 0 : a.hashCode());
result = prime * result + ((b == null) ? 0 : b.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ABid other = (ABid) obj;
if (a == null) {
if (other.a != null)
return false;
} else if (!a.equals(other.a))
return false;
if (b == null) {
if (other.b != null)
return false;
} else if (!b.equals(other.b))
return false;
return true;
}
}
pom.xml
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.7.Final</version>
</dependency>
示例代码
import java.util.Date;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class Main {
public static void main(String[] args) {
// * Init entity manager
EntityManagerFactory emf = Persistence.createEntityManagerFactory("playground");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// * Create two entities and persist them
// We must persist the entities first alone before we build and flush their relation
A a = new A();
a.setName("foo");
em.persist(a);
B b = new B();
b.setName("bar");
em.persist(b);
// * Build relationships between the two previous entities
AB ab = new AB();
ab.setA(a);
ab.setB(b);
ab.setDate(new Date());
a.getAbAssociations().add(ab);
b.getAbAssociations().add(ab);
// * Flush our changements in the database
em.getTransaction().commit();
em.close();
emf.close();
}
}
这是 Hibernate 在 Postgresql 数据库上创建的表的 sql 代码。
CREATE TABLE a
(
id_a integer NOT NULL,
name character varying(255),
CONSTRAINT a_pkey PRIMARY KEY (id_a)
)
CREATE TABLE b
(
id_b integer NOT NULL,
name character varying(255),
CONSTRAINT b_pkey PRIMARY KEY (id_b)
)
CREATE TABLE ab
(
date timestamp without time zone,
b_id_b integer NOT NULL,
a_id_a integer NOT NULL,
CONSTRAINT ab_pkey PRIMARY KEY (a_id_a, b_id_b),
CONSTRAINT fk_3exna7nsxvj1kv9i9pntmwlf1 FOREIGN KEY (a_id_a)
REFERENCES a (id_a) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fk_n3jrq53nr1elew4rytocopkbu FOREIGN KEY (b_id_b)
REFERENCES b (id_b) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
回应@valik的评论。
试试这个:
@Entity
public class AB {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Column(name = "id_ab")
private Integer id;
@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private A a;
@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private B b;
@Temporal(TemporalType.TIMESTAMP)
private Date date;
// Getters and setters...
}
我有 3 个 table 具有多对多关系
- 一个(id,name,....)主键id
- B (id, name, ....) with primary key id
- AB (id_a, id_b, date, ....) - table 与 no 的关系 主键
我可以为休眠建模 类 以便我使用 IdClass 而不是 EmbeddedId 解决方案(这样我就可以避免使用级联不必要的级别进行调用 - getId().getA())
PS 尝试混合使用这些解决方案,但没有成功:
http://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/
How to map a composite key with Hibernate?
When it comes to building relationships between entities,
the closest wall next to me and my head often join... (Stephan)
下面是实体 A 和 B 之间多对多关系的工作示例:
A.java
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class A {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Column(name="id_a")
private Integer id;
private String name;
@OneToMany(mappedBy="a",cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private List<AB> abAssociations = new ArrayList<>();
// Getters and setters...
}
B.java
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class B {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Column(name = "id_b")
private Integer id;
private String name;
@OneToMany(mappedBy = "b", cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private List<AB> abAssociations = new ArrayList<>();
// Getters and setters...
}
AB.java
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@Entity
@IdClass(ABid.class)
public class AB {
@Id
@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private A a;
@Id
@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private B b;
@Temporal(TemporalType.TIMESTAMP)
private Date date;
// Getters and setters...
}
ABid.java
import java.io.Serializable;
// The IdClass MUST implement Serializable and override #hashCode and #equals
public class ABid implements Serializable {
private static final long serialVersionUID = -2834827403836993112L;
private A a;
private B b;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((a == null) ? 0 : a.hashCode());
result = prime * result + ((b == null) ? 0 : b.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ABid other = (ABid) obj;
if (a == null) {
if (other.a != null)
return false;
} else if (!a.equals(other.a))
return false;
if (b == null) {
if (other.b != null)
return false;
} else if (!b.equals(other.b))
return false;
return true;
}
}
pom.xml
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.7.Final</version>
</dependency>
示例代码
import java.util.Date;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class Main {
public static void main(String[] args) {
// * Init entity manager
EntityManagerFactory emf = Persistence.createEntityManagerFactory("playground");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// * Create two entities and persist them
// We must persist the entities first alone before we build and flush their relation
A a = new A();
a.setName("foo");
em.persist(a);
B b = new B();
b.setName("bar");
em.persist(b);
// * Build relationships between the two previous entities
AB ab = new AB();
ab.setA(a);
ab.setB(b);
ab.setDate(new Date());
a.getAbAssociations().add(ab);
b.getAbAssociations().add(ab);
// * Flush our changements in the database
em.getTransaction().commit();
em.close();
emf.close();
}
}
这是 Hibernate 在 Postgresql 数据库上创建的表的 sql 代码。
CREATE TABLE a
(
id_a integer NOT NULL,
name character varying(255),
CONSTRAINT a_pkey PRIMARY KEY (id_a)
)
CREATE TABLE b
(
id_b integer NOT NULL,
name character varying(255),
CONSTRAINT b_pkey PRIMARY KEY (id_b)
)
CREATE TABLE ab
(
date timestamp without time zone,
b_id_b integer NOT NULL,
a_id_a integer NOT NULL,
CONSTRAINT ab_pkey PRIMARY KEY (a_id_a, b_id_b),
CONSTRAINT fk_3exna7nsxvj1kv9i9pntmwlf1 FOREIGN KEY (a_id_a)
REFERENCES a (id_a) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fk_n3jrq53nr1elew4rytocopkbu FOREIGN KEY (b_id_b)
REFERENCES b (id_b) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
回应@valik的评论。
试试这个:
@Entity
public class AB {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Column(name = "id_ab")
private Integer id;
@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private A a;
@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private B b;
@Temporal(TemporalType.TIMESTAMP)
private Date date;
// Getters and setters...
}