How do I map a triple date map to a bi-directional relationship?

I read: JPA: How to map a card with a date as a key , but I have the opposite of a question, I have a value component Map

as a date. How do I display this? Map: Map<Club, java.util.Date>

Can you show an example that includes the code for the Club class? It should be noted that this is a triple display. I'm not sure if it matters or not, Club

and Clubber

also have bi-directional communication ManyToMany

. My initial guess was this:

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;
}

      

Main:

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);

      

The exception I get when I try to save Club

with multiple Clubbers

in it:

 org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Club

      

Disappears @Transient

when added to the Clubber

joinDate

exception.

+3


source to share


2 answers


This is how your entities look like:

@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;
    }
}

      

These are the tables that this mapping generates:

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

      



This is how you link Clubber

to 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());
});

      

I created a test on GitHub to test this and it works:

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


source


In fact, the exception indicates that when the list of objects is saved, the Club

object Clubber

(collection clubbers) is not saved. The code where you save the Club, before saving Club

you need to save each one Clubber

in it, then call save

for Club

.



The @Transient annotation is used to indicate that the field is not stored in the database. why don't you get exceptions after applying @Transient

.

0


source







All Articles