简体   繁体   中英

JPA and hibernate - updating/merging one to many relationship

Firstly, here is the code

@Entity
@SequenceGenerator(name = "wordlist_seq", sequenceName = "wordlist_seq")
public class QuestionSet {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "wordlist_seq")
    private Long id;

    @Constraints.Required
    private String name;

    @Constraints.Required
    private String questionType;

    @Constraints.Required
    @ManyToOne
    @PrimaryKeyJoinColumn
    private User owner;

    public String getQuestionType() {
        return questionType;
    }

    public void setQuestionType(String questionType) {
        this.questionType = questionType;
    }

    @OneToMany(cascade = CascadeType.ALL)
    private List<Question> questions;
....

and here is some sample operation

@SecureSocial.SecuredAction
@play.db.jpa.Transactional
public static Result test(){
    QuestionSet set = questionSetDAO.findByID(QuestionSet.class, 100L);
    List<Question> questions = new ArrayList<Question>();
    OpenQuestion question = new OpenQuestion();
    question.setQuestion("a");
    question.setAnswer("b");
    questions.add(question);
    set.setQuestions(questions);
    questionSetDAO.merge(set);
    return ok();
}

now, when I am updating some instance of QuestionSet class I am fetching it from databse, create new list of questions (it may contain some new ones w/o id set, it may contain questions with existing id's - those are for updating).

Now, when I invoke merge method of entity manager I am getting this exceptions:

play.api.Application$$anon$1: Execution exception[[RollbackException: Error while committing the transaction]]
    at play.api.Application$class.handleError(Application.scala:289) ~[play_2.10.jar:2.1.1]
    at play.api.DefaultApplication.handleError(Application.scala:383) [play_2.10.jar:2.1.1]
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anon$2$$anonfun$handle$1.apply(PlayDefaultUpstreamHandler.scala:144) [play_2.10.jar:2.1.1]
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anon$2$$anonfun$handle$1.apply(PlayDefaultUpstreamHandler.scala:140) [play_2.10.jar:2.1.1]
    at play.api.libs.concurrent.PlayPromise$$anonfun$extend1$1.apply(Promise.scala:113) [play_2.10.jar:2.1.1]
    at play.api.libs.concurrent.PlayPromise$$anonfun$extend1$1.apply(Promise.scala:113) [play_2.10.jar:2.1.1]
javax.persistence.RollbackException: Error while committing the transaction
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:93) ~[hibernate-entitymanager-3.6.9.Final.jar:3.6.9.Final]
    at play.db.jpa.JPA.withTransaction(JPA.java:107) ~[play-java-jpa_2.10.jar:2.1.1]
    at play.db.jpa.TransactionalAction.call(TransactionalAction.java:14) ~[play-java-jpa_2.10.jar:2.1.1]
    at securesocial.core.java.SecureSocial$Secured.call(SecureSocial.java:218) ~[securesocial_2.10-master-SNAPSHOT.jar:master-SNAPSHOT]
    at play.core.j.JavaAction$$anon$2.apply(JavaAction.scala:74) ~[play_2.10.jar:2.1.1]
    at play.core.j.JavaAction$$anon$2.apply(JavaAction.scala:73) ~[play_2.10.jar:2.1.1]
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387) ~[hibernate-entitymanager-3.6.9.Final.jar:3.6.9.Final]
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1315) ~[hibernate-entitymanager-3.6.9.Final.jar:3.6.9.Final]
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:81) ~[hibernate-entitymanager-3.6.9.Final.jar:3.6.9.Final]
    at play.db.jpa.JPA.withTransaction(JPA.java:107) ~[play-java-jpa_2.10.jar:2.1.1]
    at play.db.jpa.TransactionalAction.call(TransactionalAction.java:14) ~[play-java-jpa_2.10.jar:2.1.1]
    at securesocial.core.java.SecureSocial$Secured.call(SecureSocial.java:218) ~[securesocial_2.10-master-SNAPSHOT.jar:master-SNAPSHOT]
Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96) ~[hibernate-core-3.6.9.Final.jar:3.6.9.Final]
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) ~[hibernate-core-3.6.9.Final.jar:3.6.9.Final]
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275) ~[hibernate-core-3.6.9.Final.jar:3.6.9.Final]
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268) ~[hibernate-core-3.6.9.Final.jar:3.6.9.Final]
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:188) ~[hibernate-core-3.6.9.Final.jar:3.6.9.Final]
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) ~[hibernate-core-3.6.9.Final.jar:3.6.9.Final]
Caused by: org.h2.jdbc.JdbcBatchUpdateException: Referential integrity constraint violation: "FK415AFE694BC8D057: PUBLIC.QUESTIONSET_QUESTION FOREIGN KEY(QUESTIONS_ID) REFERENCES PUBLIC.QUESTION(ID) (200)"; SQL statement:
insert into QuestionSet_Question (QuestionSet_id, questions_id) values (?, ?) [23506-168]
    at org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1121) ~[h2.jar:1.3.168]
    at com.jolbox.bonecp.StatementHandle.executeBatch(StatementHandle.java:469) ~[bonecp.jar:0.7.1.RELEASE]
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) ~[hibernate-core-3.6.9.Final.jar:3.6.9.Final]
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268) ~[hibernate-core-3.6.9.Final.jar:3.6.9.Final]
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268) ~[hibernate-core-3.6.9.Final.jar:3.6.9.Final]
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:188) ~[hibernate-core-3.6.9.Final.jar:3.6.9.Final]

In my simple example operation, question set does not contain any questions at the beginning, so the list is empty.

It would seem that hibernate tries to firstly insert questions to the join table created by OneToMany annotation and I am getting error because referenced entities are not yet in the database, but I thought that @OneToMany(cascade = CascadeType.ALL) would take care of this kind of things?

I am answering my own question because I found out that I have some left-overs from previous annotations so this constraint should not exists for my current model. I cleared the database and everything works fine now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM