从学生的角度看,与教师是多对一关联,即一个学生一定对应一个教师(而从教师角度看就是一对多,我们选定以学生为参照),所以在学生表的映射文件里面配置与教师的关联。其实,也就是我们的意图是想通过学生获取教师的信息,而不需要通过教师获取学生信息,这些是限定条件。所以必须能从Student的一方get到Teacher,因而就在学生里配置关联。
student表对应的映射文件和持久化类分别为:
映射文件Student.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
<hibernate-mapping>
<class name="org.shirdrn.entity.Student" table="student">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="sno" type="java.lang.String">
<column name="sno" length="10" not-null="true" />
</property>
<property name="sname" type="java.lang.String">
<column name="sname" length="50" not-null="true" />
</property>
<property name="dept" type="java.lang.String">
<column name="dept" length="50" />
</property>
<many-to-one name="teacher"
column="id"
class="org.shirdrn.entity.Teacher"
insert="false"
update="false"
cascade="save-update">
</many-to-one>
</class>
</hibernate-mapping>
持久化类Student.java:
package org.shirdrn.entity;
public class Student implements java.io.Serializable {
private Integer id;
private String sno;
private String sname;
private String dept;
private Teacher teacher;
public Student() {
}
public Student(String sno, String sname) {
this.sno = sno;
this.sname = sname;
}
public Student(String sno, String sname, String dept) {
this.sno = sno;
this.sname = sname;
this.dept = dept;
}
// Property accessors
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getSno() {
return this.sno;
}
public void setSno(String sno) {
this.sno = sno;
}
public String getSname() {
return this.sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getDept() {
return this.dept;
}
public void setDept(String dept) {
this.dept = dept;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
}
teacher表对应的映射文件和持久化类分别为:
映射文件Teacher.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
<hibernate-mapping>
<class name="org.shirdrn.entity.Teacher" table="teacher" schema="dbo" catalog="hibernate">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="tname" type="java.lang.String">
<column name="tname" length="50" not-null="true" />
</property>
</class>
</hibernate-mapping>
持久化类Teacher.java:
package org.shirdrn.entity;
public class Teacher implements java.io.Serializable {
// Fields
private Integer id;
private String tname;
// Constructors
public Teacher() {
}
public Teacher(String tname) {
this.tname = tname;
}
// Property accessors
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTname() {
return this.tname;
}
public void setTname(String tname) {
this.tname = tname;
}
}
建立测试类为MyTest.java如下:
package org.shirdrn.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.shirdrn.HibernateSessionFactory;
import org.shirdrn.entity.Student;
import org.shirdrn.entity.Teacher;
public class MyTest {
public static void main(String[] args){
Session session = HibernateSessionFactory.getSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
Student stu = new Student();
stu.setSno("2008002");
stu.setSname("shirdrn");
Teacher t = new Teacher();
t.setTname("王老师");
stu.setTeacher(t);
session.save(stu);
System.out.println("success");
tx.commit();
}
catch(Exception e){
tx.rollback();
e.printStackTrace();
}
finally{
HibernateSessionFactory.closeSession();
}
}
}
在many-to-one里面配置了 cascade="save-update",级联存储更新。在向student表插入记录的同时,也在对应的teacher表里面插入一条记录,因为一个学生一定对应一个教师,而且配置了关联,而且又是级联保存,在控制台上可以看到:
Hibernate: insert into hibernate.dbo.teacher (tname) values (?) select scope_identity()
Hibernate: insert into student (sno, sname, dept) values (?, ?, ?) select scope_identity()
可以看到,是先向teacher表插入记录,当Hibernate映射文件加载的时候,检测到cascade="save-update"配置,在程序执行到stu.setTeacher(t);的时候,就已经确定要对teacher表执行insert操作。
如果 不设置 cascade="save-update",则只执行了一条插入语句,只向学生表插入了一条记录:
Hibernate: insert into student (sno, sname, dept) values (?, ?, ?) select scope_identity()
但是如果insert="false" update="false"没有指定,则会创建SessionFactory失败,出现下面的异常:
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.
%%%% Error Creating SessionFactory %%%%
org.hibernate.MappingException: Repeated column in mapping for entity: org.shirdrn.entity.Student column: id (should be mapped with insert="false" update="false")
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:504)
at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:526)
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:544)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:335)
at org.hibernate.mapping.RootClass.validate(RootClass.java:188)
at org.hibernate.cfg.Configuration.validate(Configuration.java:839)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1000)
at org.shirdrn.HibernateSessionFactory.rebuildSessionFactory(HibernateSessionFactory.java:60)
at org.shirdrn.HibernateSessionFactory.getSession(HibernateSessionFactory.java:43)
at org.shirdrn.test.MyTest.main(MyTest.java:11)
Exception in thread "main" java.lang.NullPointerException
at org.shirdrn.test.MyTest.main(MyTest.java:26)
我认为异常的原因是重复配置导致的。因为insert和update的默认值都是true,表明Student随时可执行插入更新操作。而我们使用cascade="save-update"又配置了一次,虽然是在关联中配置的,但是Student也是关联的一方,因此异常提示Repeated column。
然而,并不是说,如果在Student.hbm.xml的many-to-one中配置insert="false" update="false"而且也不配置cascade="save-update",执行测试程序就不会执行插入操作了,象下面这样:
<many-to-one name="teacher"
column="id"
class="org.shirdrn.entity.Teacher"
insert="false"
update="false"
>
</many-to-one>
仍然可以向student表插入记录,因为那个配置insert="false" update="false"是对于关联来说的,但看Student本身,它的insert还是true,所以执行插入操作。
分享到:
相关推荐
在Java的持久化框架Hibernate中,多对一(ManyToOne)关联关系是一种常见的对象关系映射(ORM)场景。这种关系通常出现在一个实体类拥有多条与另一个实体类相关的记录,而另一个实体类可能只有一条对应的记录。例如...
包含《多对多双向关联映射》《多对一单向关联映射》《多对一双向关联映射》《一对多单向关联映射》等文档,并有图解及例子,非常适合新手学习,尤其是刚刚接触hibernate,对映射关系不清楚的。。。。
总结来说,Hibernate中的一对一主键关联映射允许两个实体共享同一个主键,实现单向关联时只需在依赖方添加对另一方的引用。在实际应用中,应根据业务需求谨慎选择关联类型,以确保数据的完整性和一致性。
本教程主要聚焦于Hibernate中的一个关键概念——关系映射,特别是多对一单向关联的实现。这种关联类型常出现在数据库设计中,比如一个部门可以有多名员工,但一个员工只属于一个部门。 首先,我们要理解多对一关系...
本主题将深入探讨如何使用Hibernate通过主键来实现一对一的单向关联关系,并提供相关的源码分析。 首先,我们需要理解一对一关联关系的基本概念。在数据库中,一对一关系意味着两个表中的每一条记录都对应另一表中...
本练习主要关注的是Hibernate中的单向多对多关联映射,这是一种常见的关系数据库设计模式,用于表示两个实体间复杂的关系。 在多对多关联中,两个实体类可以相互拥有多个实例,但只在一个方向上建立关联。例如,...
本篇主要探讨的是如何在Hibernate中实现一对多的单向关联映射。 一、概念理解 一对多关联意味着一个实体(如部门)可以有多个关联实体(如员工),而反过来,每个员工只属于一个部门。单向关联则表示只有部门知道其...
在Java的持久化框架Hibernate中,一对一(One-to-One)关联映射是常见的...以上就是关于Hibernate一对一唯一外键关联映射(单向关联)的详细说明。通过这种方式,我们可以轻松地在Java应用中处理数据库的一对一关系。
本篇文章将深入探讨Hibernate中的一对一外键单向关联。 首先,一对一外键关联指的是一个实体通过外键直接引用另一个实体的主键。在单向关联中,只有其中一个实体知道另一个实体的存在,而另一个实体则无感知。这种...
这篇博客文章“hibernate一对多关联映射(单向关联)”将深入讲解如何配置和使用这种映射关系。 在单向关联中,只有一个实体知道另一个实体的存在,也就是说,只有父实体("一"的一端)有对子实体("多"的一端)的...
**标题详解:**“Hibernate教程04_关系映射之一对一单向外键关联” 在Hibernate框架中,关系映射是数据库表之间的关联在对象模型中的体现。本教程重点讲解了一对一(One-to-One)单向外键关联的实现方法。在数据库...
在Java的持久化框架Hibernate中,单向一对多关联映射是常见的数据关系处理方式,尤其是在处理数据库中的实体类和表之间的关系时。本主题主要关注如何使用注解来实现这种映射。Hibernate通过注解使得对象关系映射...
在Hibernate中,一对一关联映射分为单向和双向。单向一对一映射通常涉及一个实体持有另一个实体的引用,而双向一对一映射则意味着两个实体都可以互相引用。这种关联关系在数据库层面通常通过主键外键约束来实现,但...
在Java持久化框架Hibernate中,一对多外键单向关联是一种常见的关系映射方式,它描述了一对多的关系,其中一个实体(例如Person)可以与多个其他实体(例如Address)相关联,而关联的方向只从多方(Address)指向...
本项目“Hibernate学习:单向多对一关联 工程”专注于讲解Hibernate中的单向多对一关联映射,这是数据库设计中常见的关系类型,尤其在处理具有层次结构的数据时。 单向多对一关联指的是在一个实体类中有一个引用,...
总的来说,这篇博客和相关代码示例为开发者提供了一个理解和实现Hibernate中多对多单向关联的起点,帮助他们更好地处理复杂的数据库关系映射。学习和实践这部分内容对于提升Java后端开发能力,特别是使用Hibernate...
“Hibernate基于外键的一对多单向关联”这个标题指的是在Java持久化框架Hibernate中,如何通过外键实现一个实体类(如订单)与另一个实体类(如商品)之间的一对多关系,并且这种关联是单向的,即从订单端可以访问到...