我有2个实体,学生和电话,以及他们之间的一对多关系。
@Entity
@Table(name = "STUDENT")
public class Student {
private long studentId;
private String studentName;
private Set<Phone> studentPhoneNumbers = new HashSet<Phone>(0);
public Student() {
}
public Student(String studentName, Set<Phone> studentPhoneNumbers) {
this.studentName = studentName;
this.studentPhoneNumbers = studentPhoneNumbers;
}
@Id
@GeneratedValue
@Column(name = "STUDENT_ID")
public long getStudentId() {
return this.studentId;
}
public void setStudentId(long studentId) {
this.studentId = studentId;
}
@Column(name = "STUDENT_NAME", nullable = false, length = 100)
public String getStudentName() {
return this.studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
@OneToMany (mappedBy="student", cascade = CascadeType.ALL)
public Set<Phone> getStudentPhoneNumbers() {
return this.studentPhoneNumbers;
}
public void setStudentPhoneNumbers(Set<Phone> studentPhoneNumbers) {
this.studentPhoneNumbers = studentPhoneNumbers;
}
}
@Entity
@Table(name = "PHONE")
public class Phone {
private long phoneId;
private String phoneType;
private String phoneNumber;
private Student student;
private Set<Student> students = new HashSet<Student>(0);
public Phone() {
}
public Phone(String phoneType, String phoneNumber) {
this.phoneType = phoneType;
this.phoneNumber = phoneNumber;
}
@Id
@GeneratedValue
@Column(name = "PHONE_ID")
public long getPhoneId() {
return this.phoneId;
}
public void setPhoneId(long phoneId) {
this.phoneId = phoneId;
}
@Column(name = "PHONE_TYPE", nullable = false, length=10)
public String getPhoneType() {
return this.phoneType;
}
public void setPhoneType(String phoneType) {
this.phoneType = phoneType;
}
@Column(name = "PHONE_NUMBER", nullable = false, length=15)
public String getPhoneNumber() {
return this.phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn (name="STUDENT_ID")
public Student getStudent() {
return this.student;
}
public void setStudent(Student student) {
this.student = student;
}
这是applicationContext.xml的代码:
...
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/Project"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="annotatedClasses">
<list>
<value>com.domain.Student</value>
<value>com.domain.Phone</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
<bean id="myClassDAO" class="com.project.dao.ClassDAOImpl">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
...
我的ClassDAOImpl看起来像:
public class ClassDAOImpl{
private HibernateTemplate hibernateTemplate;
private Session session;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
this.session = sessionFactory.openSession();
}
public void updateStudent(){
Transaction transaction = session.beginTransaction();
Student s = (Student)session.get(Student.class, new Long(1));
Set<Phone> phoneNumbers =s.getStudentPhoneNumbers();
phoneNumbers.add(new Phone ("house","12342342"));
s.setStudentPhoneNumbers(phoneNumbers);
session.update(s);
transaction.commit();
}
}
我只想给主键为“1”的学生添加电话。为此,首先我得到学生,然后通过添加新的手机来更新手机。最后我更新了实体Student。 我查看了我的Phone表,新手机上有一个新行,但是外键(STUDENT_ID)出现“Null”值,因此没有注册关系。我怎么能解决它?
提前致谢
答案 0 :(得分:0)
在JPA / Hibernate中,您始终必须自己维护双向关联的双方。关联的拥有方是Hibernate用来知道关联是否存在或已经改变的一方,它们是 no mappedBy
属性的一方。
在您的情况下,Phone
是拥有方。因此,如果你没有设置你创建的手机的student
属性,Hibernate会认为手机没有链接到任何用户,即使用户将手机放在手机列表中也是如此。
附注:阅读有关声明式事务管理的Spring文档。你真的不应该做什么来获得一个开放的会话和管理交易。
答案 1 :(得分:0)
试试这个:
public void updateStudent(){
Transaction transaction = session.beginTransaction();
Student s = (Student)session.get(Student.class, new Long(1));
Set<Phone> phoneNumbers =s.getStudentPhoneNumbers();
Phone phone = new Phone("house", "12342342");
phone.setStudent(s);
phoneNumbers.add(phone);
s.setStudentPhoneNumbers(phoneNumbers);
session.update(s);
transaction.commit();
}
或者更好的是,向学生添加一个实用工具方法,如下所示:
public void addPhone(Phone phone) {
if (phone == null) throw new IllegalArgumentException("Cannot add a null phone to a Student!");
phone.setStudent(this);
getStudents().add(phone);
}
并将updateStudent方法更改为:
public void updateStudent(){
Transaction transaction = session.beginTransaction();
Student s = (Student)session.get(Student.class, new Long(1));
Phone phone = new Phone("house", "12342342");
s.addPhone(phone);
session.update(s);
transaction.commit();
}
另外,请确保已将级联选项设置为级联到手机。
答案 2 :(得分:0)
在双向实体关系中,始终建议连接关系的两侧。尽管您确实拥有关系的拥有方(未标记为“mappedBy”的一方)。
例如,当您创建新关系时,请在学生实体上调用getStudentPhoneNumbers()。addPhone(newPhone)以及在电话实体上调用setStudent()。