如何使用双向关系映射日期三元映射?

时间:2015-06-04 23:46:45

标签: java database hibernate collections orm

我已阅读:JPA: How to map a Map with Date as key但我的问题与此相反,我将Map的值组件作为日期。我该如何映射?地图:Map<Club, java.util.Date>您能否展示一个包含俱乐部课程代码的示例?应该注意,这是三元映射。我不确定这是否重要,但ClubClubber也有双向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时,该异常消失了。

2 个答案:

答案 0 :(得分:1)

这就是你的实体应该是这样的:

@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

这是您将ClubberClub

相关联的方式
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')

答案 1 :(得分:0)

实际上,异常表示保存Club Clubber(收集俱乐部成员)的Club对象列表时不会保存。保存俱乐部的代码,在保存Clubber之前,您必须将每个save保存在其中,然后致电Club @Transient

应用@Transient注释用于指示不在数据库中保留字段。这就是为什么你在申请$(document).ready(function() { $(".websites-container").delay(5000).queue(function() { $(this).addClass("active"); }); $(".websites-container").delay(8000).queue(function() { $(this).addClass("gone") }); }); 后没有异常的原因。