Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate - ManyToOne & Inheritance / JOINED / mappedBy

I have some problems with inheritance mapping. Here my database structure:

enter image description here

And associated entities:

AbstractEntity:

@MappedSuperclass
public abstract class AbstractEntity<ID extends Serializable> implements Serializable {

@Id @GeneratedValue(strategy = IDENTITY)
@Column(unique = true, updatable = false, nullable = false)
private ID id;

public ID getId() {
return id;
}
@SuppressWarnings("unused")
public void setId(ID id) {
this.id = id;
}

UserAcitvity entity:

@Entity @Table(name = "user_activity")
@Inheritance(strategy = JOINED)
@AttributeOverride(name = "id", column = @Column(name = "ua_id"))
public abstract class UserActivity extends AbstractEntity<Long> {

@ManyToOne(cascade = { MERGE, PERSIST }, fetch = LAZY)
@JoinColumn(name = "ua_user_id")
private User user;

...
}

Comment entity:

@Entity @Table(name = "comment")
@PrimaryKeyJoinColumn(name = "cm_id")
public class Comment extends UserActivity {

@ManyToOne(cascade = { MERGE, PERSIST }, fetch = LAZY)
@JoinColumn(name = "cm_question_id")
private Question question;

...
}

Question entity:

@Entity @Table(name = "question")
@PrimaryKeyJoinColumn(name = "qs_id")
public class Question extends UserActivity {

...

@OneToMany(fetch = LAZY, cascade = ALL, mappedBy = "question")
private List<Answer> answers = new ArrayList<>();

@OneToMany(fetch = LAZY, cascade = ALL, mappedBy = "question")
private List<Comment> comments = new ArrayList<>();

...
}

Answer entity:

@Entity @Table(name = "answer")
@PrimaryKeyJoinColumn(name = "asw_id")
public class Answer extends UserActivity {

@ManyToOne(cascade = { MERGE, PERSIST }, fetch = LAZY)
@JoinColumn(name = "asw_question_id")
private Question question;

...
}

and User entity:

@Entity @Table(name = "user")
@AttributeOverride(name = "id", column = @Column(name = "user_id"))
public class User extends AbstractEntity<Long> {

...
@OneToMany(cascade = REMOVE)
private List<Question> questions = new ArrayList<>();

@OneToMany(cascade = REMOVE)
private List<Answer> answers = new ArrayList<>();

@OneToMany(cascade = REMOVE)
private List<Comment> comments = new ArrayList<>();
...
}

Problem:

When I try to save or delete a User I get an exceptions:

org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [insert into user_question (user_user_id, questions_qs_id) values (?, ?)]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement

and:

org.hibernate.engine.jdbc.spi.SqlExceptionHelper : 147 = user lacks privilege or object not found: USER_ANSWER

Hibernate is trying to create a table: user_question and user_answer which me do not need.

What I should doing for fixes ?

like image 483
Anton Dozortsev Avatar asked Mar 07 '14 13:03

Anton Dozortsev


1 Answers

I don't think you can achieve this by mapping the ManyToOne association to User generically in the UserActivity entity. That's probably too confusing for the JPA provider (Hibernate).

Instead, I think you need to map the association to User in each of the Question, Answer and Comment entities. Yes, I know that would be duplicated code, but it looks like the only way you will then be able to qualify the OneToMany mappings in User using the mappedBy reference.

For instance, your Question entity would have an association defined as:

@ManyToOne(cascade = { MERGE, PERSIST }, fetch = LAZY)
@JoinColumn(name = "ua_user_id")
private User questionUser;

Depending on how clever (or not) Hibernate is about the above association, you may need to specify the table="USER_ACTIVITY" in the JoinColumn annotation.

Then the User would have the OneToMany as:

@OneToMany(mappedBy="questionUser", cascade = REMOVE)
private List<Question> questions = new ArrayList<>();

Similarly for each of Answer and Comment.

Of course, I haven't tried this, so I could be wrong.

like image 106
DuncanKinnear Avatar answered Sep 17 '22 23:09

DuncanKinnear