标签:hibernate 入门教程 一对一配置 外键方式 共享主键
上一章我们学了一下Hibernate的配置和单张表的操作,这一章说一下Hibernate中一对一的配置
Hibernate入门教程 第二章
Hibernate的一对一单边双边配置、以及增删改查
预备知识:
1、fetch ,可以设置fetch = "select" 和 fetch = "join"
fetch ="select"是在查询的时候先查询出一端的实体,然后在根据一端的查询出多端的实体,会产生1+n条sql语句;
fetch = "join"是在查询的时候使用外连接进行查询,不会差生1+n的现象。
2、lazy策略可以用在:
* <class>标签上:可以取值true/false
* <property>标签上,可以取值true/false,这个特性需要类增强
* <set>/<list>等集合上,可以取值为true/false/extra
* <one-to-one>/<many-to-one>等标签上,可以取值false/proxy/no-proxy
lazy大家应该都熟悉了,就是延迟加载,可以设置lazy = "true" , lazy = "false" lazy ="proxy" 。
我在这里要说的主要问题是lazy 和fetch配合使用的问题:
1、当lazy="true" fetch = "select" 的时候 ,这个时候是使用了延迟策略,开始只查询出一端实体,多端的不会查询,只有当用到的时候才会发出sql语句去查询 ;
2、当lazy="false" fetch = "select" 的时候 ,这个时候是使没有用延迟策略,同时查询出一端和多端,同时产生1+n条sql.
3、当lazy="true"/lazy="false" fetch ="join"的时候,自己认为这个时候延迟已经没有什么用了,因为采用的是外连接查询,同时把一端和多端都查询出来了,延迟没有起作用。
3、cascade的取值
all : 所有情况下均进行关联操作。
none:所有情况下均不进行关联操作。这是默认值。
save-update:在执行save/update/saveOrUpdate时进行关联操作。
delete:在执行delete时进行关联操作。
Hibernate一对一配置分为共享主键和外键2中方式,我们先看外键的方式:
一、下面我们以班级和班长为例讲解
1、班级类:
public class Clazz implements java.io.Serializable { // Fields private Integer classId; private String className; private Monitor monitor; // Constructors /** default constructor */ public Clazz() { } /** full constructor */ // Property accessors public Integer getClassId() { return this.classId; } public Clazz(String className, Monitor monitor) { this.className = className; this.monitor = monitor; } public void setClassId(Integer classId) { this.classId = classId; } public String getClassName() { return this.className; } public void setClassName(String className) { this.className = className; } public Monitor getMonitor() { return monitor; } public void setMonitor(Monitor monitor) { this.monitor = monitor; } }
<hibernate-mapping> <class name="com.sunny.entity50.Clazz" table="clazz" catalog="test100"> <id name="classId" type="java.lang.Integer"> <column name="class_id" /> <generator class="identity"></generator> </id> <property name="className" type="java.lang.String"> <column name="class_name" length="50" /> </property> <one-to-one class="com.sunny.entity50.Monitor" name="monitor"/> </class> </hibernate-mapping>
public class Monitor implements java.io.Serializable { // Fields private Integer monitorId; private Clazz clazz; private String monitorName; // Constructors /** default constructor */ public Monitor() { } /** full constructor */ public Monitor(Clazz clazz, String monitorName) { this.clazz = clazz; this.monitorName = monitorName; } // Property accessors public Integer getMonitorId() { return this.monitorId; } public void setMonitorId(Integer monitorId) { this.monitorId = monitorId; } public Clazz getClazz() { return this.clazz; } public void setClazz(Clazz clazz) { this.clazz = clazz; } public String getMonitorName() { return this.monitorName; } public void setMonitorName(String monitorName) { this.monitorName = monitorName; } }4、班长类配置文件Monitor.hbm.xml
<hibernate-mapping> <class name="com.sunny.entity50.Monitor" table="monitor" catalog="test100"> <id name="monitorId" type="java.lang.Integer"> <column name="monitor_id" /> <generator class="identity"></generator> </id> <many-to-one name="clazz" class="com.sunny.entity50.Clazz" unique="true"> <column name="class_id" /> </many-to-one> <property name="monitorName" type="java.lang.String"> <column name="monitor_name" length="50" /> </property> </class> </hibernate-mapping>
1、添加数据
//添加数据 public static void fun1(){ Session session = HibernateSessionFactory.getSessionFactory().openSession(); Transaction trans = session.beginTransaction(); Clazz c = new Clazz(); c.setClassName("应用数学"); session.save(c); Monitor m = new Monitor(); m.setMonitorName("张攀"); m.setClazz(c); session.save(m); trans.commit(); session.close(); }
//查询数据 public static void fun2(){ Session session = HibernateSessionFactory.getSessionFactory().openSession(); Clazz c = (Clazz)session.get(Clazz.class,1); //Monitor m = (Monitor)session.get(Monitor.class, 1); System.out.println(c.getMonitor().getMonitorName()); }
//删除数据 public static void fun3(){ Session session = HibernateSessionFactory.getSessionFactory().openSession(); Transaction trans = session.beginTransaction(); Clazz c = (Clazz)session.get(Clazz.class,4); session.delete(c); trans.commit(); session.close(); }注意:fun3()将会报错有的时候,比如说现在数据库里现在有一条班级记录,一条班长记录,班长中应用了班级的id,那么在fun3中你直接删除了一个班级,那么这里面是有外键约束的,所以将有可能报错,如何解决呢?我我们需要在Clazz.hbm.xml中配置一下关联
<one-to-one class="com.sunny.entity50.Monitor" name="monitor" cascade="all"/>//cascade写为delete也是可以的
如果这样你也要小心了,如你不小心删除了一个班级,那么这个班级的班长的记录也就没有了,所以关联还是要慎用的,我们最后用捕获错误的方式来解决或者判断的方式来解决
4、修改
修改简单就不贴出代码了,与上一章的修改一样,见我上一篇文章
说明:
1、关于这样外键方式的一对一配置就说完了,在说一下,Hibernate事务的事情,Hibernate报错的时候是当我们commit的时候,如果commit失败,那么数据库操作是不成功的,将会报错,下面我代码演示一个情况
public static void fun5(){ Session session = HibernateSessionFactory.getSessionFactory().openSession(); Transaction trans = session.beginTransaction(); Clazz c = new Clazz(); c.setClassName("应用数学"); session.save(c); Monitor m = new Monitor(); m.setMonitorId(2); m.setMonitorName("张攀"); m.setClazz(c); session.save(m); trans.commit(); trans.rollback();//测试地方 session.close(); }我的意图就是测一下Hibernate的事务,我想让我刚才插入数据库中的数据回滚,但是不幸的是代码报错了;
错误如下:
Exception in thread "main" org.hibernate.TransactionException: Transaction not successfully
started
at org.hibernate.transaction.JDBCTransaction.rollback(JDBCTransaction.java:183)
at com.sunny.test.Demo50.fun5(Demo50.java:53)
at com.sunny.test.Demo50.main(Demo50.java:23)
意思就说我的事务没有开启,可以我的事务命名开了啊,其实是这样的,当我们commit成功了时候,Hibernate将把事务给关闭了,所有报了上面那个错误,如果commit失败了,那么事务是没有关闭的,这里大家要注意
2、如果要配置单边的关系就对应的配置文件中和代码中的关系删除即可。
二、主键关联的配置方式
以学生和饭卡为例,一个学生一张饭卡
1、学生类
public class Student implements java.io.Serializable { // Fields private Integer studentId; private String studentName; private Card card; // Constructors /** default constructor */ public Student() { } /** full constructor */ public Student(String studentName, Card card) { this.studentName = studentName; this.card = card; } // Property accessors public Integer getStudentId() { return this.studentId; } public void setStudentId(Integer studentId) { this.studentId = studentId; } public String getStudentName() { return this.studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } public Card getCard() { return this.card; } public void setCard(Card card) { this.card = card; } }2、学生配置文件Student.hbm.xml
<?xml version="1.0" encoding="utf-8"?> <!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 Persistence Tools --> <hibernate-mapping> <class name="com.sunny.entity51.Student" table="student" catalog="test100"> <id name="studentId" type="java.lang.Integer"> <column name="student_id" /> <generator class="identity"></generator> </id> <property name="studentName" type="java.lang.String"> <column name="student_name" length="50" /> </property> <one-to-one name="card" class="com.sunny.entity51.Card"></one-to-one> </class> </hibernate-mapping>3、饭卡类
public class Card implements java.io.Serializable { // Fields private Integer studentId; private Student student; private String cardNum; // Constructors /** default constructor */ public Card() { } /** minimal constructor */ public Card(Student student) { this.student = student; } /** full constructor */ public Card(Student student, String cardNum) { this.student = student; this.cardNum = cardNum; } // Property accessors public Integer getStudentId() { return this.studentId; } public void setStudentId(Integer studentId) { this.studentId = studentId; } public Student getStudent() { return this.student; } public void setStudent(Student student) { this.student = student; } public String getCardNum() { return this.cardNum; } public void setCardNum(String cardNum) { this.cardNum = cardNum; } }
<?xml version="1.0" encoding="utf-8"?> <!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 Persistence Tools --> <hibernate-mapping> <class name="com.sunny.entity51.Card" table="card" catalog="test100"> <id name="studentId" type="java.lang.Integer"> <column name="student_id" /> <generator class="foreign"> <!-- 这里是最重要的地方,主键是外键 --> <param name="property">student</param> </generator> </id> <one-to-one name="student" class="com.sunny.entity51.Student" constrained="true"></one-to-one> <property name="cardNum" type="java.lang.String"> <column name="card_num" length="50" /> </property> </class> </hibernate-mapping>二、数据库操作
这里只给出一个插入的例子,其他的和上面的操作差不多
public static void fun1(){ Session session = HibernateSessionFactory.getSessionFactory().openSession(); Transaction trans = session.beginTransaction(); Student stu = new Student(); stu.setStudentName("tomcat"); session.save(stu); Card c = new Card(); c.setCardNum("123456"); c.setStudent(stu); session.save(c); trans.commit(); }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:hibernate 入门教程 一对一配置 外键方式 共享主键
原文地址:http://blog.csdn.net/zhangpan19910604/article/details/46661037