问题描述
我的域模型图如下所示:
正如你所看到的,我在学生和考勤之间以及考勤和研讨会之间有一对一的关系。
以下是学生和考勤班,以及我的助手类(初始化程序)。
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 {
/ *开始所有类字段* /
@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;
/ *结束字段* /
@OneToMany(mappedBy =student,cascade = CascadeType.ALL)
private Set< Attendance>考勤=新的HashSet<考勤>();
$ b / **
*默认构造函数
* /
public Student(){
}
$ b $ / **
* Secondary构造函数自动创建一个Student
* @param名字
* @param姓氏
* @param电子邮件
* @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;
}
/ *连接学生的方法<>>考勤* /
/ **
* @return一个新的hashset包含学生
* /
public HashSet< Attendance>的所有出勤率的
*< p> getAttendance(){
返回新的HashSet<出席>(出席);
}
/ **
* @param考勤
* @param研讨会
* /
公共无效addAttendance(出席考勤,研讨会研讨会){
if(attendance!= null& seminar!= null){
attendance.setStudent(this);
attendance.setSeminar(研讨会);
attendance.setRegisterDate((new SimpleCalendar(Calendar.getInstance()))); / * xreiazomaste na orizete I timi apo to sistima automata * /
}
}
/ **
*参数从HashSet中移除
* /
public void removeAttendance(出席考勤){
attendance.setStudent(null);
}
/ **
* @return考勤HashSet
* /
public Set< Attendance> findAttendance(){
return attendance;
$ b / *(非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;
}
学生学生=(学生)其他;
// Integer a = getStudentId();
// Integer b = theStudent.getStudentId();
if(!(getIdCard()== null)?theStudent.getIdCard()== null:getIdCard()。equals(theStudent.getIdCard())){
return false;
}
返回true;
$ b $ *(非Javadoc)
* @see java.lang.Object#hashCode()
* /
public int hashCode ){
return idCard == null? 0:idCard.hashCode();
}
}
出勤班
/ **
*
* /
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 = )
public class Attendance {
public Attendance(){
this.registerDate = new SimpleCalendar(Calendar.getInstance());
$ b @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)
私有布尔成功;
@ManyToOne
@JoinColumn(name =studentId,nullable = false)
私立学生;
@OneToMany(mappedBy =attendance,cascade = CascadeType.ALL)
private Set< Absence>缺席=新的HashSet<缺席>();
@ManyToOne
@JoinColumn(name =seminarId,nullable = false)
private研讨会研讨会;
@OneToMany(mappedBy =attendance,cascade = CascadeType.ALL)
private Set< Payment>付款=新HashSet< Payment>(); / *<<<< * /
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;
$ b / **
* @返回学生
* /
public Student getStudent(){
return student;
}
/ **
* @param学生学生设置
* /
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);
$ b / **
* @返回研讨会
* /
公开研讨会getSeminar(){
返回研讨会;
}
/ **
* @param研讨会设定
* /
的研讨会public void setSeminar(研讨会研讨会){
// 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< Absence> getAbsence(){
返回新的HashSet< Absence>(不存在);
public void addAbsence(缺席缺席,SimpleCalendar日期){
if(缺席!= null&& date!= null){
缺席。 setAttendance(本);
/ * stelnoume tin imerominia pou kataxorei I gramamteia oti elipe o foititis * /
absence.setDate(date);
}
}
/ **
* @return Absence HashSet
* /
public Set< Absence> findAbsence(){
return absence;
}
/ **
* @return HashSet<付款>
* /
public HashSet< Payment> getPayment(){
返回新的HashSet<付款>(付款);
}
public void addPayment(Payment payment,SimpleCalendar date){
if(payment!= null&&date!= null){
payment。 setAttendance(本);
/ * stelnoume tin imerominia pou kataxorei I gramamteia oti elipe o foititis * /
//absence.setDate(date);
}
}
/ **
* @return支付哈希集合
* /
public Set< Payment> findPayment(){
返回付款;
$ b / *(非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;
}
参加考勤=(考勤)其他;
// Integer a = getStudentId();
// Integer b = theStudent.getStudentId();
if(!(getStudent()== null)?theAttendance.getStudent()== null:getStudent()。equals(theAttendance.getStudent())){
return false;如果(!(getSeminar()== null)$ a
?theAttendance.getSeminar()== null:getSeminar()。equals(theAttendance.getSeminar())){
return false ;
}
返回true;
$ b $ *(非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();
返回结果;
}
/ * int result = 0;
result = getStudent()== null?结果:13 * result + getStudent()。hashCode();
result = getSeminar()== null?结果:13 * result + getSeminar()。hashCode();
返回结果; * /
}
}
初始化类
package com.seminars.persistence;
import java.util.Calendar;
导入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;
$ b公共类初始化程序{
/ * EntityManager em = DatabaseFactory.createEntityManager();
EntityTransaction tx = em.getTransaction(); * /
//删除数据库中的所有数据
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(从\中删除Payment \);
query.executeUpdate();
query = em.createNativeQuery(从\删除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();
学生s1 =新生(george,antoniou,[email protected],antoniou,密码,998456);
s1.setStudentId(1);
学生s2 =新生(ilias,butsikakis,[email protected],ilias,butsi,98756423);
s2.setStudentId(2);
研讨会sem1 =新研讨会(1,Java,5,500,2,新的SimpleCalendar(2013,1,5),新的SimpleCalendar(2013,2,5),100);
sem1.setSeminarId(1);
出席att =新出勤();
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();
$ b $ * public void prepareData1(){
//πρινεισάγουμεταδεδομέναδιαγράφουμεόπιρες
eraseData();
学生s1 =新生(george,antoniou,[email protected],antoniou,密码,998456);
s1.setStudentId(1);
学生s2 =新生(ilias,butsikakis,[email protected],ilias,butsi,98756423);
s2.setStudentId(2);
研讨会sem1 =新研讨会(1,Java,5,500,2,新的SimpleCalendar(2013,1,5),新的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();
/ *注意总是记住:
* 1)开放实体经理,
* 2)打开交易
* 3)创建物品
*其他您需要使用合并或你会得到一个分离的异常!
* * /
//s1=em.merge(s1);
/ *学生s1 =新生(george,antoniou,[email protected],antoniou,密码,998456);
s1.setStudentId(1);
学生s2 =新生(ilias,butsikakis,[email protected],ilias,butsi,98756423);
s2.setStudentId(2);
研讨会sem1 =新研讨会(1,Java,5,500,2,新的SimpleCalendar(2013,1,5),新的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(); * /
//}
}
该项目主要通过JUnit测试进行检查,因此在初始化类中我们有一个PrepareData方法,该方法创建一些样例数据以用于每个检查以及一个删除方法以确保每次检查都使用相同的数据完成。
在试图检查Student和Attendance之间的连接之前,一切似乎都正常。我在初始化器中创建了一个新的Attendance对象,以测试学生是否可以在研讨会中注册ok,并且我收到了很多异常消息。
注意到尽管(尽管它显示和在控制台中)是
$ b
我检查以确保注释和级联是在正确的地方,但没有结果...
我也尝试改变项目在initilizer类中保存的顺序,但随后出现其他错误b
$ b
** javax.persistence.PersistenceException:org.hibernate.PropertyValueException:not-null属性引用null或瞬态值:com.seminars.domain。 Attendance.seminar **在org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1235)
在org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168)
。在org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1174)
处com.seminars.persistence org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:674)
。 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。评估(InvokeMethod.java:20)
在org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
在org.junit.inte rnal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
处org.junit.runners.BlockJUnit4ClassRunner org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
。 runChild(BlockJUnit4ClassRunner.java:44)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access $ 000(ParentRunner.java:41 )
在org.junit.runners.ParentRunner $ 1.evaluate(ParentRunner.java:173)
在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)
在org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner。 RemoteTestRunner.run(RemoteTestRunner.java:390)
在org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
引起的:org.hibernate.PropertyValueException:非空属性引用null或瞬态值:com.seminars.domain.Attendance.seminar
在org.hibernate.engine.Nullability.checkNullability(Nullability.java:101)
在org.hibernate。 event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:313)
处org.hibernate.event.def org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
。 AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
在org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3Persis tEventListener.java:69)在org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:179
)
在org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:
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
下面是在更改初始化程序类中的项目顺序之前出现的例外列表:
> javax.persistence.PersistenceException:
> org.hibernate.exception.ConstraintViolationException:could
>在
>执行本机批量操作查询org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1235)
>在
> org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168)
>在
> org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:1245)
>在
> org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:108)
>在
> com.seminars.persistence.Initializer.eraseData(Initializer.java:37)
>在
> com.seminars.services.ManageStudentServiceTest.empty(ManageStudentServiceTest.java:64)
>在
> 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)
>在
> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
>在
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
>在
> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
>在
> org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
>在
> org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
>在
> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
>在
> 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)
>在org.junit.runners.ParentRunner $ 1.evaluate(ParentRunner.java:173)
>在
> org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
>在
> 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)
>在
> org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
>在
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
>在
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
>在
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
>在
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
>造成者:org.hibernate.exception.ConstraintViolationException:could
>不在
>执行本机批量操作查询org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
>在
> org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
>在
> org.hibernate.engine.query.NativeSQLQueryPlan.performExecuteUpdate(NativeSQLQueryPlan.java:219)
>在
> org.hibernate.impl.SessionImpl.executeNativeUpdate(SessionImpl.java:1300)
>在
> org.hibernate.impl.SQLQueryImpl.executeUpdate(SQLQueryImpl.java:365)
>在
> org.hibernate.ejb.QueryImpl.internalExecuteUpdate(QueryImpl.java:183)
>在
> org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:99)
> ... 27更多由:org.h2.jdbc.JdbcSQLException引用:引用
>完整性约束违规:FKE7E9BF09F9FEB38B:
> PUBLIC。出席外国关键(学生)参考
>公共。学生(studentId); SQL语句:从
删除> 学生[23003-135]在
> 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)
>在
> org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:395)
>在
> 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)
>在
> org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:127)
>在
> org.hibernate.engine.query.NativeSQLQueryPlan.performExecuteUpdate(NativeSQLQueryPlan.java:210)
> ... 31 more
你能帮我确定为什么会发生这些错误吗?我尝试了所有我能想到的,但很少成功的东西。任何帮助将不胜感激。
在删除考勤机之前,您正试图从数据库中删除所有学生。但出席对学生有一个外键。因此,如果数据库允许您删除学生,那么您将拥有一个不连贯的数据库:引用不存在的学生的出勤率。
因此,您必须在删除学生之前删除出席者。
请注意,实体之间存在的级联是无关紧要的,因为插入,更新和删除查询完全忽略它们。
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 Set<Attendance> attendance = new HashSet<Attendance>() ;
/**
* 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
* <p>all attendances of the student
*/
public HashSet<Attendance> getAttendance(){
return new HashSet<Attendance>(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<Attendance> 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 Set<Absence> absence = new HashSet<Absence>() ;
@ManyToOne
@JoinColumn(name="seminarId", nullable = false)
private Seminar seminar;
@OneToMany(mappedBy = "attendance",cascade=CascadeType.ALL)
private Set<Payment> payment = new HashSet<Payment>() ;/*<<<*/
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<Absence> getAbsence(){
return new HashSet<Absence>(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<Absence> findAbsence(){
return absence;
}
/**
* @return HashSet<Payment>
*/
public HashSet<Payment> getPayment(){
return new HashSet<Payment>(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<Payment> 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","[email protected]","antoniou","password","998456");
s1.setStudentId(1);
Student s2=new Student("ilias","butsikakis","[email protected]","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","[email protected]","antoniou","password","998456");
s1.setStudentId(1);
Student s2=new Student("ilias","butsikakis","[email protected]","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","[email protected]","antoniou","password","998456");
s1.setStudentId(1);
Student s2=new Student("ilias","butsikakis","[email protected]","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
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
Can you please help me determine why these errors Happen? I tried everything I could think but with little success. Any help would be greatly appreciated.
You're trying to delete all the students from the database before deleting the attendances. But attendance has a foreign key to student. So, if the database let you delete the students, you would have an incoherent database: attendances referencing students that don't exist.
So you must delete attendances before deleting students.
Note that the cascades existing between entities are irrelevant, because insert, update and delete queries completely ignore them.
这篇关于JPA引用完整性约束违规oneToMany和批量操作查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!