Java – @ manytoone mapping is not applicable to connection inheritance
I have the following database structure:
CREATE TABLE `author` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT,`name` varchar(255) NOT NULL,`email` varchar(255) NOT NULL,`password` varchar(255) NOT NULL,PRIMARY KEY (`id`)); CREATE TABLE `message` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT,`title` varchar(500) NOT NULL,`text` varchar(50000) NOT NULL,`author_id` int(10) unsigned DEFAULT NULL,`creation_date` datetime NOT NULL,`last_update_date` datetime NOT NULL,PRIMARY KEY (`id`),KEY `author_id_fk` (`author_id`),CONSTRAINT `message_ibfk_1` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`)); CREATE TABLE `comment` ( `id` int(10) unsigned NOT NULL,`post_id` int(10) unsigned NOT NULL,KEY `message_id_fk` (`id`),KEY `post_id_fk` (`post_id`),CONSTRAINT `comment_ibfk_1` FOREIGN KEY (`id`) REFERENCES `message` (`id`),CONSTRAINT `comment_ibfk_2` FOREIGN KEY (`post_id`) REFERENCES `post` (`id`)); CREATE TABLE `post` ( `id` int(10) unsigned NOT NULL,CONSTRAINT `post_ibfk_1` FOREIGN KEY (`id`) REFERENCES `message` (`id`) ON DELETE CASCADE);
And the following mapping using hibernate (3.5.4-final):
@Entity
@Table(name = "author")
public class Author {
private Long id = 0L;
private String name;
private String email;
private String password;
private Set<Post> posts;
private Set<Comment> comments;
@Id
@Column(name = "id")
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "email")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Column(name = "password")
public String getpassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@OneToMany(mappedBy = "author")
public Set<Post> getPosts() {
return posts;
}
public void setPosts(Set<Post> posts) {
this.posts = posts;
}
@OneToMany(mappedBy = "author")
public Set<Comment> getComments() {
return comments;
}
public void setComments(Set<Comment> comments) {
this.comments = comments;
}
}
@MappedSuperclass
@Table(name = "message")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Message implements Serializable {
private Long id;
private String title;
private String text;
private Author author;
private Date creationDate;
private Date lastUpdateDate;
@Id
@Column(name = "id")
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "title")
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Column(name = "text")
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
@ManyToOne
@JoinColumn(name = "author_id")
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
@Column(name = "creation_date")
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
@Column(name = "last_update_date")
public Date getLastUpdateDate() {
return lastUpdateDate;
}
public void setLastUpdateDate(Date lastUpdateDate) {
this.lastUpdateDate = lastUpdateDate;
}
}
@Entity
@Table(name = "comment")
@PrimaryKeyJoinColumn(name="id")
public class Comment extends Message {
private static final long serialVersionUID = 1L;
private Post post;
@ManyToOne
@JoinColumn(name = "post_id")
public Post getPost() {
return post;
}
public void setPost(Post post) {
this.post = post;
}
}
@Entity
@Table(name = "post")
@PrimaryKeyJoinColumn(name="id")
public class Post extends Message {
private static final long serialVersionUID = 1L;
private Set<Comment> comments;
@OneToMany(mappedBy = "post")
public Set<Comment> getComments() {
return comments;
}
public void setComments(Set<Comment> comments) {
this.comments = comments;
}
}
The main idea is that both comment and post inherit from message. I hope they have a two-way relationship But when I run the following code:
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = session.beginTransaction();
Author author = new Author();
author.setName("mike");
author.setPassword("123");
author.setEmail("mike@gmail.com");
Post post = new Post();
post.setAuthor(author);
post.setCreationDate(new Date());
post.setLastUpdateDate(new Date());
post.setText("Text");
post.setTitle("Title");
Long authorId = (Long)session.save(author);
Long postId = (Long)session.save(post);
tx.commit();
I received the following error:
ERROR JDBCExceptionReporter:101 - UnkNown column 'author_id' in 'field list'
Exception in thread "main" org.hibernate.exception.sqlGrammarException: Could not insert: [org.blogsample.mappingbeans.Post]
at org.hibernate.exception.sqlStateConverter.convert(sqlStateConverter.java:92)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:64)
Update as @ JB nizet mentioned earlier, I changed @ mappedsuperclass to @ entity, and then I got another error. Mappedby refers to an unknown target entity attribute: org blogsample. mappingbeans. Comment. Author, which is solved by changing the DB structure (deleting the author_id) from the message table, adding it to each comment, publishing and creating the foreign key of this column) and moving the author (and getter / setter with mapping) to the comment and post classes
Solution
Your message class should not use the @ mappedsuperclass annotation, but the @ entity annotation@ Mappedsuperclass means that the entity extending this class inherits columns and associations from the superclass, but these columns and associations are in the table of the subclass author_ ID is not in comment table or post table It is in the message table
And @ table can only be used with entities It is not a mapped superclass. It is only used to inherit fields and associations, but it is not mapped to its own table like an entity
