I want to create a table, where the id is come strings composed. This is how I did is following some examples and documentation:
@Entity
@Table(name = "media_locator")
public class MediaLocator {
private List<MediaObject> mediaObjects;
private MediaLocatorPK primaryKey = new MediaLocatorPK();
// @Id
// @GeneratedValue(strategy = GenerationType.AUTO)
// @Column(name = "id", unique = true, nullable = false)
// public int getId() {
// return id;
// }
//
// public void setId(int id) {
// this.id = id;
// }
@EmbeddedId
public MediaLocatorPK getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(MediaLocatorPK primaryKey) {
this.primaryKey = primaryKey;
}
// @Column(name = "location", length = 200)
public String getLocation() {
return primaryKey.getLocation();
}
public void setLocation(String location) {
this.primaryKey.setLocation(location);
}
// @Column(name = "description", length = 200, nullable = false)
public String getDescription() {
return primaryKey.getDescription();
}
public void setDescription(String description) {
this.primaryKey.setDescription(description);
}
// @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="mediaLocator")
// public List<MediaObject> getMediaObjects() {
// return mediaObjects;
// }
//
// public void setMediaObjects(List<MediaObject> mediaObjects) {
// mediaObjects = mediaObjects;
// }
@ManyToMany(
cascade={CascadeType.ALL},
fetch=FetchType.LAZY)
@JoinTable(name = "media_object_location",
joinColumns=@JoinColumn(name="mediaLocator_id"),
inverseJoinColumns=@JoinColumn(name="mediaObject_id"))
public List<MediaObject> getMediaObjects() {
return mediaObjects;
}
public void setMediaObjects(List<MediaObject> mediaObjects) {
this.mediaObjects = mediaObjects;
}
// @Column(name = "protocol", length = 200, nullable = false)
public String getProtocol() {
return primaryKey.getProtocol();
}
public void setProtocol(String protocol) {
this.primaryKey.setProtocol(protocol);
}
// @Column(name = "host", length = 200, nullable = false)
public String getHost() {
return primaryKey.getHost();
}
public void setHost(String host) {
this.primaryKey.setHost(host);
}
// @Column(name = "port", length = 200, nullable = false)
public String getPort() {
return primaryKey.getPort();
}
public void setPort(String port) {
this.primaryKey.setPort(port);
}
// @Column(name = "path", length = 200, nullable = false)
public String getPath() {
return primaryKey.getPath();
}
public void setPath(String path) {
this.primaryKey.setPath(path);
}
@Embeddable class MediaLocatorPK implements Serializable
{
private String location;
private String description;
private String protocol;
private String host;
private String port;
private String path;
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
Before, I had an id auto generated, and each atribute had a colum in the table, @Column(name = "location", length = 200), for instance.
In this way I can not store the data due to referencies from relations with other objects
Caused by: org.hibernate.AnnotationException: A Foreign key refering com.app.MediaLocator from com.app.MediaObject has the wrong number of column. should be 6
at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:429)
at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1443)
at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1262)
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:693)
at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:628)
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:65)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1686)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1393)
at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1345)
at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:717)
at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:211)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1469)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1409)
This specific relation is:
@ManyToMany(
cascade={CascadeType.ALL},
fetch=FetchType.LAZY)
@JoinTable(name = "media_object_location",
joinColumns=@JoinColumn(name="mediaLocator_id"),
inverseJoinColumns=@JoinColumn(name="mediaObject_id"))
public List<MediaObject> getMediaObjects() {
return mediaObjects;
}
public void setMediaObjects(List<MediaObject> mediaObjects) {
this.mediaObjects = mediaObjects;
}
And from mediaObject side:
@ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.LAZY, mappedBy = "mediaObjects")
public List<MediaLocator> getMediaLocators() {
return mediaLocators;
}
public void setMediaLocators(List<MediaLocator> mediaLocators) {
this.mediaLocators = mediaLocators;
}
what am I doing wrong?
Thanks in advance
Once you have moved properties to the embeddable class you need to remove them from the main class, there will be just one reference of your embedded class, so in your example you need to remove all properties like location from your
MediaLocatorclass.Also what is property
iddoing in yourMediaLocator? Since there is no specific column annotation in your class hibernate will try to map each and every attribute to the table column, it will succeed in that mapping if the naming of both the property and table column are same.If you dont need
idthen either remove it or mark it as@Transient.This piece of code will reproduce the same error what you are getting.
Student Class
Student PK Class:
Address Class
If you run this piece of code and try to save an instance of Address you will get
My manytomany in
StudentMTMis broken.Now this piece will work as it should be:
Student Class
Student PK
Address Class – No change from the first version.
In the second version JoinColumn is part of Student and mapping knows where it is mapping to.