I have an entity for storing Workshops where I am using a composite primary key.
I do not like the concept of auto-generated keys and until now have mostly used business derived keys, such as email id etc for entities. However over here, the workshop entity did not appear to have a natural candidate for primary key, so I went for a composite key.I created a WorkshopIdType
which is an enum containing the three possible workshops that will be organised
public enum WorkshopIdType implements Serializable {
FOUNDATION("FND"), INTERMEIDATE("IMT"), ADVANCED("ADV");
private final String name;
private WorkshopIdType(String name) {
this.name = name;
}
@Override
public String toString() {
return this.name;
}
public boolean equals(String otherName) {
return (otherName == null) ? false : name.equals(otherName);
}
}
And then I have an Embeddable class for primary key; the combination of workshop type and date appears to me as the best fit for primary key in this scenario
@Embeddable
@Access(AccessType.FIELD)
public class WorkshopId implements Serializable {
private static final long serialVersionUID = -7287847106009163526L;
private String workshopIdType;
private Date date;
@Column(name = "id", nullable = false)
public String getWorkshopIdType() {
return workshopIdType;
}
public void setWorkshopIdType(WorkshopIdType workshopIdType) {
this.workshopIdType = workshopIdType.toString();
}
@Temporal(TemporalType.DATE)
@Column(name = "date", nullable = false)
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
The entity also has a ManyToOne relationship with Venue
, here again, the Venues are actually 5 of the pre-designated centres across three cities
@Entity
public class Workshop implements Serializable {
private static final long serialVersionUID = -5516160437873476233L;
private WorkshopId id;
private Venue venue;
private Integer seatsAvailable;
@EmbeddedId
public WorkshopId getId() {
return id;
}
public void setId(WorkshopId id) {
this.id = id;
}
@ManyToOne
@JoinTable(name = "workshop_venue", joinColumns = { @JoinColumn(name = "workshop_id", referencedColumnName = "id") }, inverseJoinColumns = { @JoinColumn(name = "venue_name", referencedColumnName = "name") })
public Venue getVenue() {
return venue;
}
public void setVenue(Venue venue) {
this.venue = venue;
}
@Column(name = "seats_available", nullable = false)
public Integer getSeatsAvailable() {
return seatsAvailable;
}
public void setSeatsAvailable(Integer seatsAvailable) {
this.seatsAvailable = seatsAvailable;
}
}
Problem is mapping this ManyToOne with a JoinTable in case of a composite key
@ManyToOne
@JoinTable(name = "workshop_venue", joinColumns = { @JoinColumn(name = "workshop_id", referencedColumnName = "id") }, inverseJoinColumns = { @JoinColumn(name = "venue_name", referencedColumnName = "name") })
public Venue getVenue() {
return venue;
}
This won't work as I had suspected, it cannot find a column with logical name "id". I am going with ManyToOne with JoinTable because there can be a scenario where users should get to know is there a training scheduled for the given Venue. How do I specify the referencedColumnName in this case?
Either that or I got it all wrong in the way I am modelling this?