My domain model diagram looks like this:
As you can see I have an oneToMany releation between Student and Attendance and between Attendance and Seminar.
Below are the Student and Attendance Classes, as well as my helper class( Initializer).
package com.seminars.domain; import java.util.Calendar; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; import com.seminars.util.SimpleCalendar; @Entity @Table(name="Student") public class Student { /*start all class fields*/ @Id //@GenericGenerator(name="kaugen" , strategy="increment") //@GeneratedValue(generator="kaugen") @Column(name="studentId") //@GeneratedValue(strategy=GenerationType.AUTO) private int studentId; @Column(name="firstname", length=50, nullable = false) private String firstname; @Column(name="lastname", length=50, nullable = false) private String lastname; @Column(name="email", length=50, nullable = false) private String email; @Column(name="username", length=50, nullable = false) private String username; @Column(name="password", length=50, nullable = false) private String password; @Column(name="idCard", length=50, nullable = false) private String idCard; /* end fields*/ @OneToMany(mappedBy = "student",cascade=CascadeType.ALL) private Setattendance = new HashSet () ; /** * default constructor */ public Student(){ } /** * Secondary Constructor to automatically create a Student * @param firstname * @param lastname * @param email * @param username * @param password * @param idcard */ public Student(String firstname,String lastname,String email, String username,String password, String idcard){ this.setFirstname(firstname); this.setLastname(lastname); this.setEmail(email); this.setIdCard(idcard); this.setPassword(password); this.setUsername(username); } public int getStudentId() { return studentId; } public void setStudentId(int studentId) { this.studentId = studentId; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getIdCard() { return idCard; } public void setIdCard(String idCard) { this.idCard = idCard; } /*Methods for connecting Student<------->Attendance*/ /** * @return a new hashset contain * all attendances of the student */ public HashSet
getAttendance(){ return new HashSet (attendance); } /** * @param attendance * @param seminar */ public void addAttendance(Attendance attendance, Seminar seminar){ if(attendance!=null & seminar!=null){ attendance.setStudent(this); attendance.setSeminar(seminar); attendance.setRegisterDate((new SimpleCalendar(Calendar.getInstance()))); /* xreiazomaste na orizete I timi apo to sistima automata*/ } } /** * @param attendance to remove from HashSet */ public void removeAttendance(Attendance attendance){ attendance.setStudent(null); } /** * @return Attendance HashSet */ public Set findAttendance(){ return attendance; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object other) { if ( other == null) { return false; } if (this == other) { return true; } if (! (other instanceof Student)) { return false; } Student theStudent = (Student) other; //Integer a=getStudentId(); //Integer b=theStudent.getStudentId(); if(!(getIdCard()==null) ? theStudent.getIdCard()==null : getIdCard().equals(theStudent.getIdCard())){ return false; } return true; } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ public int hashCode() { return idCard == null ? 0 : idCard.hashCode(); } }
Attendance Class
/** * */ package com.seminars.domain; import java.util.Calendar; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.junit.Assert; import org.junit.Test; import com.seminars.util.SimpleCalendar; /** * @author Ilias * */ @Entity @Table(name = "Attendance") public class Attendance { public Attendance() { this.registerDate=new SimpleCalendar(Calendar.getInstance()); } @Id @Column(name="attendanceId") @GeneratedValue(strategy=GenerationType.AUTO) private int attendanceId; @Column(name = "registerDate", length = 200, nullable = false) //@Temporal(TemporalType.DATE) @org.hibernate.annotations.Type( type="com.seminars.persistence.SimpleCalendarCustomType") private SimpleCalendar registerDate; @Column(name = "success") private boolean success; @ManyToOne @JoinColumn(name="studentId", nullable = false) private Student student; @OneToMany(mappedBy = "attendance",cascade=CascadeType.ALL) private Setabsence = new HashSet () ; @ManyToOne @JoinColumn(name="seminarId", nullable = false) private Seminar seminar; @OneToMany(mappedBy = "attendance",cascade=CascadeType.ALL) private Set payment = new HashSet () ;/*<<<*/ public SimpleCalendar getRegisterDate() { return registerDate; } public void setRegisterDate(SimpleCalendar registerDate) { this.registerDate = registerDate; } public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } /** * @return the student */ public Student getStudent() { return student; } /** * @param student the student to set */ public void setStudent(Student student) { //this.student = student.findAttendance().add(this); if (this.student != null) { this.student.findAttendance().remove(this); } this.student = student; if (this.student != null) { this.student.findAttendance().add(this); } } /** * @return the seminar */ public Seminar getSeminar() { return seminar; } /** * @param seminar the seminar to set */ public void setSeminar(Seminar seminar) { //this.student = student.findAttendance().add(this); if (this.seminar != null) { this.seminar.findAttendance().remove(this); } this.seminar = seminar; if (this.seminar != null) { this.seminar.findAttendance().add(this); } } public HashSet getAbsence(){ return new HashSet (absence); } public void addAbsence(Absence absence, SimpleCalendar date){ if(absence!=null && date!=null){ absence.setAttendance(this); /*stelnoume tin imerominia pou kataxorei I gramamteia oti elipe o foititis*/ absence.setDate(date); } } /** * @return Absence HashSet */ public Set findAbsence(){ return absence; } /** * @return HashSet */ public HashSet getPayment(){ return new HashSet (payment); } public void addPayment(Payment payment, SimpleCalendar date){ if(payment!=null && date!=null){ payment.setAttendance(this); /*stelnoume tin imerominia pou kataxorei I gramamteia oti elipe o foititis*/ //absence.setDate(date); } } /** * @return Payment HashSet */ public Set findPayment(){ return payment; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object other) { if ( other == null) { return false; } if (this == other) { return true; } if (! (other instanceof Attendance)) { return false; } Attendance theAttendance = (Attendance) other; //Integer a=getStudentId(); //Integer b=theStudent.getStudentId(); if(!(getStudent()==null) ? theAttendance.getStudent()==null : getStudent().equals(theAttendance.getStudent())){ return false; } if(!(getSeminar()==null) ? theAttendance.getSeminar()==null : getSeminar().equals(theAttendance.getSeminar())){ return false; } return true; } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ public int hashCode() { if(student==null && seminar==null){ return 0; } else { int result=0; if(student!=null) result+= 13*getStudent().hashCode()/*+getSeminar().hashCode()*/; if(seminar!=null) result+= 13*getSeminar().hashCode(); return result; } /*int result = 0; result = getStudent() == null ? result : 13 * result + getStudent().hashCode(); result = getSeminar() == null ? result : 13 * result + getSeminar().hashCode(); return result; */ } }
Initializer Class
package com.seminars.persistence; import java.util.Calendar; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; import javax.persistence.Query; import com.seminars.domain.Attendance; import com.seminars.domain.Seminar; import com.seminars.domain.Student; import com.seminars.util.SimpleCalendar; public class Initializer { /* EntityManager em = DatabaseFactory.createEntityManager(); EntityTransaction tx = em.getTransaction();*/ //delete all data from database public void eraseData() { EntityManager em = DatabaseFactory.getCurrentEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); Query query = em.createNativeQuery("delete from \"Student\""); query.executeUpdate(); query = em.createNativeQuery("delete from \"Absence\""); query.executeUpdate(); query = em.createNativeQuery("delete from \"Attendance\""); query.executeUpdate(); query = em.createNativeQuery("delete from \"Payment\""); query.executeUpdate(); query = em.createNativeQuery("delete from \"Seminar\""); query.executeUpdate(); query = em.createNativeQuery("delete from \"Program\""); query.executeUpdate(); tx.commit(); em.close(); } public void prepareData() { // ???? ????????? ?? ???????? ??????????? ??? ??????? eraseData(); EntityManager em = DatabaseFactory.createEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); Student s1=new Student("george","antoniou","antoniougeo@hotmail.com","antoniou","password","998456"); s1.setStudentId(1); Student s2=new Student("ilias","butsikakis","ili@hotmail.com","ilias","butsi","98756423"); s2.setStudentId(2); Seminar sem1=new Seminar(1, "Java", 5,500, 2, new SimpleCalendar(2013,1,5), new SimpleCalendar(2013,2,5),"100"); sem1.setSeminarId(1); Attendance att=new Attendance(); att.setRegisterDate(new SimpleCalendar(Calendar.getInstance())); //s1.addAttendance(att, sem1); //s1=em.merge(s1); //s2=em.merge(s2); //sem1=em.merge(sem1); //em.persist(att); em.persist(s1); em.persist(s2); em.persist(sem1); s1.addAttendance(att, sem1); em.persist(att); s1=em.merge(s1); em.persist(s1); tx.commit(); em.close(); } /*public void prepareData1() { // ???? ????????? ?? ???????? ??????????? ??? ??????? eraseData(); Student s1=new Student("george","antoniou","antoniougeo@hotmail.com","antoniou","password","998456"); s1.setStudentId(1); Student s2=new Student("ilias","butsikakis","ili@hotmail.com","ilias","butsi","98756423"); s2.setStudentId(2); Seminar sem1=new Seminar(1, "Java", 5,500, 2, new SimpleCalendar(2013,1,5), new SimpleCalendar(2013,2,5),"100"); //EntityManager em = DatabaseFactory.createEntityManager(); EntityManager em = DatabaseFactory.createEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); em.persist(s1); em.persist(s2); tx.commit(); em.close(); /*NOTE ALWAYS REMEMBER: * 1)Open entity Manager, * 2)Open Transaction * 3)Create Items * else You will need to use merge or you will get a detached exception!!! * */ //s1=em.merge(s1); /* Student s1=new Student("george","antoniou","antoniougeo@hotmail.com","antoniou","password","998456"); s1.setStudentId(1); Student s2=new Student("ilias","butsikakis","ili@hotmail.com","ilias","butsi","98756423"); s2.setStudentId(2); Seminar sem1=new Seminar(1, "Java", 5,500, 2, new SimpleCalendar(2013,1,5), new SimpleCalendar(2013,2,5),"100"); s1=em.merge(s1); s2=em.merge(s2); sem1=em.merge(sem1); em.persist(s1); em.persist(s2); em.persist(sem1); tx.commit(); em.close();*/ /*EntityManagerFactory emf = Persistence.createEntityManagerFactory("library"); EntityManager em = emf.createEntityManager();*/ //} }
The project is mostly checked through JUnit Tests, so in Initializer Class we have a PrepareData method which creates some sample data to use in each check as well a delete method to make sure each check is done with the same data.
Before trying to check the connection between Student and Attendance everything seemed to work ok. I went and created a new Attendance Object in initializer to test if the Student can enroll "ok" in a seminar and I got a lot of Exception messages.
The one I noticed the most though (as it is shown and in the console) is the
3781 [main] ERROR org.hibernate.util.JDBCExceptionReporter - Referential integrity constraint violation: "FKE7E9BF09F9FEB38B: PUBLIC.""Attendance"" FOREIGN KEY(STUDENT) REFERENCES PUBLIC.""Student""(""studentId"")"; SQL statement: delete from "Student" [23003-135]
I checked to make sure the annotations and the cascades are in the right place but with no result...
I also tried changing the order the items are saved in initilizer class but then other errors appeared
**javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.seminars.domain.Attendance.seminar** at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1235) at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168) at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1174) at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:674) at com.seminars.persistence.Initializer.prepareData(Initializer.java:73) at com.seminars.services.ManageStudentServiceTest.setup(ManageStudentServiceTest.java:60) at com.seminars.services.ManageStudentServiceTest.testManageStudentService(ManageStudentServiceTest.java:97) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:44) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41) at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) at org.junit.runners.ParentRunner.run(ParentRunner.java:220) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.seminars.domain.Attendance.seminar at org.hibernate.engine.Nullability.checkNullability(Nullability.java:101) at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:313) at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204) at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130) at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69) at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:179) at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135) at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61) at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:800) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:774) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:778) at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:668) ... 27 more
Below is the Exception list that came up before changing the order of the items in the initializer class:
> javax.persistence.PersistenceException: > org.hibernate.exception.ConstraintViolationException: could not > execute native bulk manipulation query at > org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1235) > at > org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168) > at > org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:1245) > at > org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:108) > at > com.seminars.persistence.Initializer.eraseData(Initializer.java:37) > at > com.seminars.services.ManageStudentServiceTest.empty(ManageStudentServiceTest.java:64) > at > com.seminars.services.ManageStudentServiceTest.testManageStudentService(ManageStudentServiceTest.java:99) > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at > sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at > sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at > java.lang.reflect.Method.invoke(Unknown Source) at > org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) > at > org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) > at > org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) > at > org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) > at > org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) > at > org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) > at > org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) > at > org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:44) > at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180) > at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41) > at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173) > at > org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) > at > org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) > at org.junit.runners.ParentRunner.run(ParentRunner.java:220) at > org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) > at > org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) > at > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) > at > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) > at > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) > at > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) > Caused by: org.hibernate.exception.ConstraintViolationException: could > not execute native bulk manipulation query at > org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96) > at > org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) > at > org.hibernate.engine.query.NativeSQLQueryPlan.performExecuteUpdate(NativeSQLQueryPlan.java:219) > at > org.hibernate.impl.SessionImpl.executeNativeUpdate(SessionImpl.java:1300) > at > org.hibernate.impl.SQLQueryImpl.executeUpdate(SQLQueryImpl.java:365) > at > org.hibernate.ejb.QueryImpl.internalExecuteUpdate(QueryImpl.java:183) > at > org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:99) > ... 27 more Caused by: org.h2.jdbc.JdbcSQLException: Referential > integrity constraint violation: "FKE7E9BF09F9FEB38B: > PUBLIC.""Attendance"" FOREIGN KEY(STUDENT) REFERENCES > PUBLIC.""Student""(""studentId"")"; SQL statement: delete from > "Student" [23003-135] at > org.h2.message.DbException.getJdbcSQLException(DbException.java:327) > at org.h2.message.DbException.get(DbException.java:167) at > org.h2.message.DbException.get(DbException.java:144) at > org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:378) > at > org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:395) > at > org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:275) > at org.h2.table.Table.fireConstraints(Table.java:788) at > org.h2.table.Table.fireAfterRow(Table.java:805) at > org.h2.command.dml.Delete.update(Delete.java:79) at > org.h2.command.CommandContainer.update(CommandContainer.java:70) at > org.h2.command.Command.executeUpdate(Command.java:199) at > org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:141) > at > org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:127) > at > org.hibernate.engine.query.NativeSQLQueryPlan.performExecuteUpdate(NativeSQLQueryPlan.java:210) > ... 31 more
你能帮我确定一下这些错误发生的原因吗?我尝试了所有我能想到但却收效甚微的东西.任何帮助将不胜感激.
在删除考勤之前,您试图从数据库中删除所有学生.但是出勤对学生来说是一把外键.因此,如果数据库允许您删除学生,那么您将拥有一个不连贯的数据库:考虑不存在的学生的出勤率.
因此,您必须在删除学生之前删除考勤.
请注意,实体之间存在的级联是无关紧要的,因为插入,更新和删除查询完全忽略它们.