如何映射具有双向关系的三元日期映射?
How to Map a Ternary Map of Dates With a Bidirectional Relationship?
我读过:JPA: How to map a Map with Date as key 但我有相反的问题,我将 Map
的值组件作为日期。我应该如何映射这个?地图:Map<Club, java.util.Date>
你能展示一个例子,包括俱乐部 class 的代码吗?需要注意的是,这是一个三元映射。我不确定这是否重要,但 Club
和 Clubber
也有双向 ManyToMany
关系。我最初的猜测是:
public class Clubber{
@Id
@Column(name = "Clubber_Id")
private final int id;
@Temporal(TemporalType.TIMESTAMP)
@ElementCollection
@MapKeyJoinColumn(name = "id")
private final Map<Club, Date> joinDate;
@ManyToMany(cascade = CascadeType.ALL)
private final Collection<Club> clubs;
}
public class Club {
@Id
@Column(name = "Club_ID")
private final int id;
@ManyToMany(cascade = CascadeType.ALL, mappedBy = "clubs")
private final Collection<Clubber> clubbers;
}
主要:
Map<Club, Date> dates = randomGeneration(Date.class);
Collection<Club> clubs = randomGeneration(Club.class);
Clubber clubber = new Clubber(clubs, dates);
Club club = new Club(Arrays.asList(clubber));
session.saveOrUpdate(club);
当我尝试保存一个 Club
其中有几个 Clubbers
时出现的异常:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Club
当我将 @Transient
添加到 Clubber
的 joinDate
时,异常消失了。
实际上异常告诉我们在保存 Club
对象列表时 Clubber
(Collection clubbers)没有被保存。您保存俱乐部的代码,在保存 Club
之前,您必须在其中保存每个 Clubber
然后为 Club
.
调用 save
应用@Transient 注解用于表示一个字段不被持久化到数据库中。这就是为什么你在应用 @Transient
.
后没有得到异常
您的实体应如下所示:
@Entity(name = "Clubber")
public class Clubber{
@Id
@GeneratedValue
@Column(name = "Clubber_Id")
private Integer id;
@Temporal(TemporalType.TIMESTAMP)
@ElementCollection
@CollectionTable(name="CLUB_ASSIGNMENTS", joinColumns=@JoinColumn(name="Clubber_Id", referencedColumnName="Clubber_Id"))
@Column(name="CLUB_DATE")
@MapKeyJoinColumn(name = "Club_ID", referencedColumnName="Club_ID")
private Map<Club, Date> joinDate = new HashMap<>();
public Integer getId() {
return id;
}
public Map<Club, Date> getJoinDate() {
return joinDate;
}
public Collection<Club> getClubs() {
return joinDate.keySet();
}
public void addClub(Club club) {
joinDate.put(club, new Date());
//clubs.add(club);
club.getClubbers().add(this);
}
}
@Entity(name = "Club")
public class Club {
@Id
@GeneratedValue
@Column(name = "Club_ID")
private Integer id;
@ManyToMany(mappedBy = "joinDate", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Clubber> clubbers = new ArrayList<>();
public Integer getId() {
return id;
}
public List<Clubber> getClubbers() {
return clubbers;
}
}
这些是此映射生成的表:
create table CLUB_ASSIGNMENTS (Clubber_Id integer not null, CLUB_DATE timestamp, Club_ID integer not null, primary key (Clubber_Id, Club_ID))
create table Club (Club_ID integer generated by default as identity (start with 1), primary key (Club_ID))
create table Clubber (Clubber_Id integer generated by default as identity (start with 1), primary key (Clubber_Id))
alter table CLUB_ASSIGNMENTS add constraint FK_i1d8m16i8ytv7jybg8aneo9hj foreign key (Club_ID) references Club
alter table CLUB_ASSIGNMENTS add constraint FK_6oitm1mry43ga5iovtfamp3q3 foreign key (Clubber_Id) references Clubber
alter table CLUB_ASSIGNMENTS add constraint FK_3xj613grja6o0xkjeb7upms4 foreign key (CLUB_DATE) references Club
这就是将 Clubber
关联到 Club
的方式:
final Clubber clubberReference = doInTransaction(session -> {
Clubber clubber = new Clubber();
Club club = new Club();
clubber.addClub(club);
session.persist(club);
return clubber;
});
doInTransaction(session -> {
Clubber clubber = (Clubber) session.get(Clubber.class, clubberReference.getId());
assertEquals(1, clubber.getClubs().size());
assertEquals(1, clubber.getJoinDate().size());
});
我在 GitHub 上创建了一个测试来检查这个并且它有效:
insert into Club (Club_ID) values (default)
insert into Clubber (Clubber_Id) values (default)]
insert into CLUB_ASSIGNMENTS (Clubber_Id, Club_ID, CLUB_DATE) values (1, 1, '2015-06-10 16:37:36.487')
我读过:JPA: How to map a Map with Date as key 但我有相反的问题,我将 Map
的值组件作为日期。我应该如何映射这个?地图:Map<Club, java.util.Date>
你能展示一个例子,包括俱乐部 class 的代码吗?需要注意的是,这是一个三元映射。我不确定这是否重要,但 Club
和 Clubber
也有双向 ManyToMany
关系。我最初的猜测是:
public class Clubber{
@Id
@Column(name = "Clubber_Id")
private final int id;
@Temporal(TemporalType.TIMESTAMP)
@ElementCollection
@MapKeyJoinColumn(name = "id")
private final Map<Club, Date> joinDate;
@ManyToMany(cascade = CascadeType.ALL)
private final Collection<Club> clubs;
}
public class Club {
@Id
@Column(name = "Club_ID")
private final int id;
@ManyToMany(cascade = CascadeType.ALL, mappedBy = "clubs")
private final Collection<Clubber> clubbers;
}
主要:
Map<Club, Date> dates = randomGeneration(Date.class);
Collection<Club> clubs = randomGeneration(Club.class);
Clubber clubber = new Clubber(clubs, dates);
Club club = new Club(Arrays.asList(clubber));
session.saveOrUpdate(club);
当我尝试保存一个 Club
其中有几个 Clubbers
时出现的异常:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Club
当我将 @Transient
添加到 Clubber
的 joinDate
时,异常消失了。
实际上异常告诉我们在保存 Club
对象列表时 Clubber
(Collection clubbers)没有被保存。您保存俱乐部的代码,在保存 Club
之前,您必须在其中保存每个 Clubber
然后为 Club
.
save
应用@Transient 注解用于表示一个字段不被持久化到数据库中。这就是为什么你在应用 @Transient
.
您的实体应如下所示:
@Entity(name = "Clubber")
public class Clubber{
@Id
@GeneratedValue
@Column(name = "Clubber_Id")
private Integer id;
@Temporal(TemporalType.TIMESTAMP)
@ElementCollection
@CollectionTable(name="CLUB_ASSIGNMENTS", joinColumns=@JoinColumn(name="Clubber_Id", referencedColumnName="Clubber_Id"))
@Column(name="CLUB_DATE")
@MapKeyJoinColumn(name = "Club_ID", referencedColumnName="Club_ID")
private Map<Club, Date> joinDate = new HashMap<>();
public Integer getId() {
return id;
}
public Map<Club, Date> getJoinDate() {
return joinDate;
}
public Collection<Club> getClubs() {
return joinDate.keySet();
}
public void addClub(Club club) {
joinDate.put(club, new Date());
//clubs.add(club);
club.getClubbers().add(this);
}
}
@Entity(name = "Club")
public class Club {
@Id
@GeneratedValue
@Column(name = "Club_ID")
private Integer id;
@ManyToMany(mappedBy = "joinDate", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Clubber> clubbers = new ArrayList<>();
public Integer getId() {
return id;
}
public List<Clubber> getClubbers() {
return clubbers;
}
}
这些是此映射生成的表:
create table CLUB_ASSIGNMENTS (Clubber_Id integer not null, CLUB_DATE timestamp, Club_ID integer not null, primary key (Clubber_Id, Club_ID))
create table Club (Club_ID integer generated by default as identity (start with 1), primary key (Club_ID))
create table Clubber (Clubber_Id integer generated by default as identity (start with 1), primary key (Clubber_Id))
alter table CLUB_ASSIGNMENTS add constraint FK_i1d8m16i8ytv7jybg8aneo9hj foreign key (Club_ID) references Club
alter table CLUB_ASSIGNMENTS add constraint FK_6oitm1mry43ga5iovtfamp3q3 foreign key (Clubber_Id) references Clubber
alter table CLUB_ASSIGNMENTS add constraint FK_3xj613grja6o0xkjeb7upms4 foreign key (CLUB_DATE) references Club
这就是将 Clubber
关联到 Club
的方式:
final Clubber clubberReference = doInTransaction(session -> {
Clubber clubber = new Clubber();
Club club = new Club();
clubber.addClub(club);
session.persist(club);
return clubber;
});
doInTransaction(session -> {
Clubber clubber = (Clubber) session.get(Clubber.class, clubberReference.getId());
assertEquals(1, clubber.getClubs().size());
assertEquals(1, clubber.getJoinDate().size());
});
我在 GitHub 上创建了一个测试来检查这个并且它有效:
insert into Club (Club_ID) values (default)
insert into Clubber (Clubber_Id) values (default)]
insert into CLUB_ASSIGNMENTS (Clubber_Id, Club_ID, CLUB_DATE) values (1, 1, '2015-06-10 16:37:36.487')