接受的答案似乎过于复杂的@JoinTable
注释。稍微简单一点的实现只需要一个mappedBy
. UsingmappedBy
表示拥有Entity
或财产,这可能应该是referencesTo
因为这将被视为“朋友”。ManyToMany
关系可以创建一个非常复杂的图形。使用mappedBy
使代码如下:
@Entity
public class Recursion {
@Id @GeneratedValue
private Integer id;
// what entities does this entity reference?
@ManyToMany
private Set<Recursion> referencesTo;
// what entities is this entity referenced from?
@ManyToMany(mappedBy="referencesTo")
private Set<Recursion> referencesFrom;
public Recursion init() {
referencesTo = new HashSet<>();
return this;
}
// getters, setters
}
并且要使用它,您需要考虑拥有的财产是referencesTo
. 您只需要将关系放在该属性中,以便它们被引用。当您阅读Entity
回文时,假设您执行了fetch join
,JPA 将为结果创建集合。当您删除一个实体时,JPA 将删除对它的所有引用。
tx.begin();
Recursion r0 = new Recursion().init();
Recursion r1 = new Recursion().init();
Recursion r2 = new Recursion().init();
r0.getReferencesTo().add(r1);
r1.getReferencesTo().add(r2);
em.persist(r0);
em.persist(r1);
em.persist(r2);
tx.commit();
// required so that existing entities with null referencesFrom will be removed from cache.
em.clear();
for ( int i=1; i <= 3; ++i ) {
Recursion r = em.createQuery("select distinct r from Recursion r left join fetch r.referencesTo left join fetch r.referencesFrom where id = :id", Recursion.class).setParameter("id", i).getSingleResult();
System.out.println(r + " To=" + Arrays.toString(r.getReferencesTo().toArray()) + " From=" + Arrays.toString(r.getReferencesFrom().toArray()) );
}
tx.begin();
em.createQuery("delete from Recursion where id = 2").executeUpdate();
tx.commit();
// required so that existing entities with referencesTo will be removed from cache.
em.clear();
Recursion r = em.createQuery("select distinct r from Recursion r left join fetch r.referencesTo left join fetch r.referencesFrom where id = :id", Recursion.class).setParameter("id", 1).getSingleResult();
System.out.println(r + " To=" + Arrays.toString(r.getReferencesTo().toArray()) + " From=" + Arrays.toString(r.getReferencesFrom().toArray()) );
它给出了以下日志输出(始终检查生成的 SQL 语句):
Hibernate: create table Recursion (id integer not null, primary key (id))
Hibernate: create table Recursion_Recursion (referencesFrom_id integer not null, referencesTo_id integer not null, primary key (referencesFrom_id, referencesTo_id))
Hibernate: create sequence hibernate_sequence start with 1 increment by 1
Hibernate: alter table Recursion_Recursion add constraint FKsi0wfuwfs0bl19jjpofw4n8pt foreign key (referencesTo_id) references Recursion
Hibernate: alter table Recursion_Recursion add constraint FKarrkuyh2v1j5qnlui2vbpl7tk foreign key (referencesFrom_id) references Recursion
Hibernate: call next value for hibernate_sequence
Hibernate: call next value for hibernate_sequence
Hibernate: call next value for hibernate_sequence
Hibernate: insert into Recursion (id) values (?)
Hibernate: insert into Recursion (id) values (?)
Hibernate: insert into Recursion (id) values (?)
Hibernate: insert into Recursion_Recursion (referencesFrom_id, referencesTo_id) values (?, ?)
Hibernate: insert into Recursion_Recursion (referencesFrom_id, referencesTo_id) values (?, ?)
Hibernate: select distinct recursion0_.id as id1_2_0_, recursion2_.id as id1_2_1_, recursion4_.id as id1_2_2_, references1_.referencesFrom_id as referenc1_3_0__, references1_.referencesTo_id as referenc2_3_0__, references3_.referencesTo_id as referenc2_3_1__, references3_.referencesFrom_id as referenc1_3_1__ from Recursion recursion0_ left outer join Recursion_Recursion references1_ on recursion0_.id=references1_.referencesFrom_id left outer join Recursion recursion2_ on references1_.referencesTo_id=recursion2_.id left outer join Recursion_Recursion references3_ on recursion0_.id=references3_.referencesTo_id left outer join Recursion recursion4_ on references3_.referencesFrom_id=recursion4_.id where id=?
model.Recursion@7bdf6bb7 To=[model.Recursion@1bc53649] From=[]
Hibernate: select distinct recursion0_.id as id1_2_0_, recursion2_.id as id1_2_1_, recursion4_.id as id1_2_2_, references1_.referencesFrom_id as referenc1_3_0__, references1_.referencesTo_id as referenc2_3_0__, references3_.referencesTo_id as referenc2_3_1__, references3_.referencesFrom_id as referenc1_3_1__ from Recursion recursion0_ left outer join Recursion_Recursion references1_ on recursion0_.id=references1_.referencesFrom_id left outer join Recursion recursion2_ on references1_.referencesTo_id=recursion2_.id left outer join Recursion_Recursion references3_ on recursion0_.id=references3_.referencesTo_id left outer join Recursion recursion4_ on references3_.referencesFrom_id=recursion4_.id where id=?
model.Recursion@1bc53649 To=[model.Recursion@42deb43a] From=[model.Recursion@7bdf6bb7]
Hibernate: select distinct recursion0_.id as id1_2_0_, recursion2_.id as id1_2_1_, recursion4_.id as id1_2_2_, references1_.referencesFrom_id as referenc1_3_0__, references1_.referencesTo_id as referenc2_3_0__, references3_.referencesTo_id as referenc2_3_1__, references3_.referencesFrom_id as referenc1_3_1__ from Recursion recursion0_ left outer join Recursion_Recursion references1_ on recursion0_.id=references1_.referencesFrom_id left outer join Recursion recursion2_ on references1_.referencesTo_id=recursion2_.id left outer join Recursion_Recursion references3_ on recursion0_.id=references3_.referencesTo_id left outer join Recursion recursion4_ on references3_.referencesFrom_id=recursion4_.id where id=?
model.Recursion@42deb43a To=[] From=[model.Recursion@1bc53649]
Hibernate: delete from Recursion_Recursion where (referencesTo_id) in (select id from Recursion where id=2)
Hibernate: delete from Recursion_Recursion where (referencesFrom_id) in (select id from Recursion where id=2)
Hibernate: delete from Recursion where id=2
Hibernate: select distinct recursion0_.id as id1_2_0_, recursion2_.id as id1_2_1_, recursion4_.id as id1_2_2_, references1_.referencesFrom_id as referenc1_3_0__, references1_.referencesTo_id as referenc2_3_0__, references3_.referencesTo_id as referenc2_3_1__, references3_.referencesFrom_id as referenc1_3_1__ from Recursion recursion0_ left outer join Recursion_Recursion references1_ on recursion0_.id=references1_.referencesFrom_id left outer join Recursion recursion2_ on references1_.referencesTo_id=recursion2_.id left outer join Recursion_Recursion references3_ on recursion0_.id=references3_.referencesTo_id left outer join Recursion recursion4_ on references3_.referencesFrom_id=recursion4_.id where id=?
model.Recursion@6b739528 To=[] From=[]