Hi, today I've encountered a really tricky issue (at least to me). I'm using hibernate-annotations 3.4.0.GA with hibernate-core 3.3.0.SP1. I am trying to model that kind of relationship: I have Artists and each of this Artist has TopTags. For various reasons I decided to model that as a one to many instead of a many to many relationship. Let's assume for simplicity each artist has the property name, which is also the key and each Tag has a name which is also the key there. Now when using that in a one to many relationship the sets of corresponding Tags need to refer to an artist, therefore I need a composite key: artistname, tagname where artistname is also a foreign key. This results in the following classes:
Artist.class
Code:
@Entity
@Table(name = "`Artists`")
public class Artist {
@Id
private String name;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name="artist")
private List<Tag> tags;
public Artist() {
}
public Artist(
String name
) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Tag> getTags() {
return tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
}
Tag:
Code:
@Entity
@Table(name = "`Tags`")
public class TopTag {
@Id
private TagKey key;
public Tag() {
}
public TopTag(
String name,
Artist artist
) {
this.key = new TagKey();
this.key.setName(name);
this.key.setArtist(artist);
}
public String getName() {
return this.key.getName();
}
public void setKey(TagKey key) {
this.key = key;
}
public TagKey getKey() {
return key;
}
}
TagKey:
Code:
@Embeddable
public class TagKey implements Serializable {
private static final long serialVersionUID = 4318615867062316407L;
private String name;
@ManyToOne
@JoinColumn(
name = "artist",
insertable = false,
updatable = false
)
private Artist artist;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setArtist(Artist artist) {
this.artist = artist;
}
public Artist getArtist() {
return artist;
}
@Override
public int hashCode() {
[...]
}
@Override
public boolean equals(Object obj) {
[...]
}
}
Select and insert works fine. But deleting an entry from the collection fails. Let's assume the following transaction where the Tags for Artist Deftones are already set:
Code:
Artist artist = (Artist) session.createQuery(
"FROM Artist artist "
+ "WHERE artist.name = :name"
).setString("name", "Deftones").uniqueResult();
artist.getTags().remove(0);
Now this will result in the following error:
Code:
org.hibernate.exception.SQLGrammarException: could not delete collection rows: [test.package.Artist.tags#Deftones]; SQL [update `Tags` set artist=null where artist=? and artist=? and `name`=?];
[...]
Caused by: java.sql.SQLException: No value specified for parameter 3
I've ommited the rest of the stack trace as there is not anything else important. Obiously hibernate shouldn't update the corresponding row and set artist to null but delete the row. Does anyone have an idea what's going wrong? Please get back to me if anything remained unclear.
(I had to adjust the code snippets as they were coming out of a larger context, hopefully I haven't made any errors, I've also ommited the "obvious" annotations for columns etc., as you might have noticed I am annotating fields instead of accessors).
Thanks!