Hi,
i have poblem with many to many relationship. I'm using jpa with hibernate (3.5.5), postrgresql 9 database and spring mvc 3.1. I have two entities: Exam (owner) and Question with many to many relationship. The application is auto creating database's tables. It creates exam table, question table and exam_question table with exam_id column, question_id column and extra column
exam_question_id (with notnull option). When i trying to add a exam with questions the app throws an exception - ERROR org.hibernate.util.JDBCExceptionReporter - ERROR: empty value in column "exam_question_id" affects the reduction of the required value
Details: Failing row contains (null, 351, 3650). I dont know why hibernate creates that extra column and then is trying add null value to it...
Here is my code:
Code:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package pl.edu.pk.exam.domain;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.map.annotate.JsonDeserialize;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import pl.edu.pk.exam.util.JsonDateDeserializer;
import pl.edu.pk.exam.util.JsonDateSerializer;
@JsonAutoDetect
@Entity
public class Exam {
public Exam() {}
public Exam(Integer examId, Integer type, Integer duration, Boolean isEnd, Date startDate, Boolean negativeScore) {
this.examId = examId;
this.type = type;
this.duration = duration;
this.isEnd = isEnd;
this.startDate = startDate;
this.negativeScore = negativeScore;
}
@Id
@GeneratedValue(generator = "exam_id", strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "exam_id", sequenceName = "exam_id_seq", initialValue = 1)
@Column(name="exam_id")
Integer examId;
public Integer getExamId() {
return examId;
}
public void setExamId(Integer examId) {
this.examId = examId;
}
@Basic
@NotNull
@Size(min = 1, max = 512)
private String name;
public String getName() {
return name;
}
public void setName(String name){
this.name = name;
}
@Basic
Integer type;
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
@Basic
Integer duration;
public Integer getDuration() {
return duration;
}
public void setDuration(Integer duration) {
this.duration = duration;
}
@Basic
@Column(name="is_end")
private Boolean isEnd;
public Boolean getIsEnd() {
return isEnd;
}
public void setIsEnd(Boolean isEnd) {
this.isEnd = isEnd;
}
@Basic
@Column(name="start_date")
@Temporal(TemporalType.TIMESTAMP)
private Date startDate;
@JsonSerialize(using=JsonDateSerializer.class)
public Date getStartDate() {
return startDate;
}
@JsonDeserialize(using = JsonDateDeserializer.class)
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
@Basic
@Column(name="negative_score")
private Boolean negativeScore;
public Boolean getNegativeScore() {
return negativeScore;
}
public void setNegativeScore(Boolean negativeScore) {
this.negativeScore = negativeScore;
}
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(
name="exam_question",
joinColumns={@JoinColumn(name="exam_id")},
inverseJoinColumns={@JoinColumn(name="question_id")}
)
Set<Question> questions = new HashSet<Question>();
@JsonIgnore
public Set<Question> getQuestions()
{
return questions;
}
@JsonIgnore
public void setQuestions(Set<Question> questions){
this.questions = questions;
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
@JsonAutoDetect
@Entity
public class Question {
public Question() {}
public Question(Integer questionId, String question, Integer type, List<Answer> answers) {
this.questionId = questionId;
this.question = question;
this.type = type;
this.answers = answers;
}
@Id
@GeneratedValue(generator = "question_id", strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "question_id", sequenceName = "question_id_seq", initialValue = 1)
@Column(name="question_id")
Integer questionId;
public Integer getQuestionId() {
return questionId;
}
public void setQuestionId(Integer questionId) {
this.questionId = questionId;
}
@Basic
@NotNull
@Size(min = 1, max = 400)
String question;
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
@Basic
Integer type;
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
@OneToMany(cascade = CascadeType.ALL, mappedBy = "question", targetEntity = Answer.class, fetch = FetchType.LAZY)
List<Answer> answers = new ArrayList<Answer>();
List<Answer> getAnswers()
{
return answers;
}
public void setAnswers(List<Answer> answers){
this.answers = answers;
}
@ManyToOne(targetEntity = Subject.class, fetch = FetchType.EAGER)
@JoinColumn(name = "subject_id", nullable = true)
Subject subject;
// @JsonIgnore
public Subject getSubject()
{
return subject;
}
// @JsonIgnore
public void setSubject(Subject subject)
{
this.subject = subject;
}
@ManyToMany(mappedBy="questions")
private Set<Exam> exams = new HashSet<Exam>();
@JsonIgnore
public Set<Exam> getExams() {
return exams;
}
}
persistence.xml file
Code:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="examPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>exam</jta-data-source>
....
<class>pl.edu.pk.exam.domain.Exam</class>
<class>pl.edu.pk.exam.domain.Question</class>
.....
<properties>
<property name="hibernate.hbm2ddl.auto" value="validate"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
</properties>
</persistence-unit>
</persistence>
exam_question table
Any solution?