读书人

hibernate 温习 单向一对一的实现

发布时间: 2012-06-26 10:04:13 作者: rapoo

hibernate 复习 单向一对一的实现

?

hibernate中单向一对一实现有三种方式:主键关联,外键关联,表关联(自己给的名字,下面会详细说的)。

?

场景设置:

?

学生 和 校服 。

我记得我初中的时候,校服忘记在操作了,有人捡到了,但是不知道是谁的,就送到体育办公室,

于是我pdpd的跑去自己拿。

?

我想说的是: 只能从学生来找到校服,而不能从校服去找到学生,这就是单向的关系。

上代码:

?

Student:

?

package com.iteye.endual.bean1;public class Student {private int id ;private String name ;private int num ;private  XiaoFu xf = new XiaoFu() ;public Student() {}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getNum() {return num;}public void setNum(int num) {this.num = num;}public XiaoFu getXf() {return xf;}public void setXf(XiaoFu xf) {this.xf = xf;}}
?

?

?

校服类:

?

?

package com.iteye.endual.bean1;public class XiaoFu {private int id ;private String owername ;public XiaoFu() {}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getOwername() {return owername;}public void setOwername(String owername) {this.owername = owername;}}

?

?

?

hibernate的主配置文件:

??<?xml version='1.0' encoding='utf-8'?>

<!DOCTYPE hibernate-configuration PUBLIC        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"><hibernate-configuration>    <session-factory>        <!-- Database connection settings -->        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>        <property name="connection.url">jdbc:mysql://localhost/test</property>        <property name="connection.username">root</property>        <property name="connection.password">数据库密码</property>        <!-- JDBC connection pool (use the built-in)         <property name="connection.pool_size">1</property>        -->        <!-- SQL dialect -->        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>        <!-- Enable Hibernate's automatic session context management         <property name="current_session_context_class">thread</property>        -->        <!-- Disable the second-level cache         <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>        -->        <!-- Echo all executed SQL to stdout -->        <property name="show_sql">true</property>        <property name="format_sql">true</property>        <!-- Drop and re-create the database schema on startup -->        <property name="hbm2ddl.auto">create</property>   <!-- 用谁只能放谁的,他们的名字一样,要冲突的        <mapping resource="com/iteye/endual/bean1/Student.hbm.xml"/>        <mapping resource="com/iteye/endual/bean1/XiaoFu.hbm.xml"/>     -->                                                                                                                              <mapping resource="com/iteye/endual/bean2/Student.hbm.xml"/>        <mapping resource="com/iteye/endual/bean2/XiaoFu.hbm.xml"/>         <mapping resource="com/iteye/endual/bean3/Student.hbm.xml"/>        <mapping resource="com/iteye/endual/bean3/XiaoFu.hbm.xml"/>    </session-factory></hibernate-configuration>
?

?

sessionFactory 的类,创建这样要花很大大大大大大的资源的哦

?

package util;import org.hibernate.*;import org.hibernate.cfg.*;public class HibernateUtil {    private static final SessionFactory sessionFactory;    static {        try {            // Create the SessionFactory from hibernate.cfg.xml            sessionFactory = new Configuration().configure().buildSessionFactory();        } catch (Throwable ex) {            // Make sure you log the exception, as it might be swallowed            System.err.println("Initial SessionFactory creation failed." + ex);            throw new ExceptionInInitializerError(ex);        }    }    public static SessionFactory getSessionFactory() {        return sessionFactory;    }}
?

?

?

?

以下三种方式的单向一对一的实体已经创建好了,配置文件,sessionFactory的类以及好了,这个是公用的。

?

?

?

?

---------------------------------

第一种,外键关联,也是我们通常在学习数据库设计的时候用到的。

?

什么是外键关联:

就是在学生表中,加个外键,这个外键的值就是校服表的主键的值。

我们要查询学生,通过学生的主键查询,查到学生的信息,然后就能查到这个外键的值,根据这个值那么可以到

校服表中去查询校服的信息了。

?

hibernate是面向对象的,所以在个外键是不需要我们在实体中去设置的,需要在配置文件中进行配置的。

?

看配置文件:

student

?

<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping >    <class name="com.iteye.endual.bean2.Student" table="t_stu2">        <id name="id" column="stu_id"> <!-- 设置主键 -->            <generator column="stu_name" />              <!--  <one-to-one name="card" foreign-key="idx" >        </one-to-one>     -->        <many-to-one name="xf" column="fk_id" unique="true" cascade="all"></many-to-one>    </class></hibernate-mapping>
?

?

?

<many-to-one name="xf" column="fk_id" unique="true" cascade="all">

?

?

? ? 一对一的单向关系中,就是多对一的特殊情况,所以用到了many to one 的标签。这个标签有个属性是

?

? ? ?unique="true",表示这个是一对一的关系。(为什么多开发一套标签来支持一对一呢, ? ?弄 ? ? ?的这么麻烦要拿 ? ?别人的修改下。)

?

cascade="all" 这是表示级联的意思,就是主如此更新的话,那么连接它的也更新,删除也一样,插入也一样。

?

?

? ? ?column="fk_id"? 这个是设置了外键的名字,会自动插入到student的表中的去,这个就是校服表的外键,这个值就是校服 ? 表主键的值。

?

?

校服表的配置文件:

?

<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping >    <class name="com.iteye.endual.bean2.XiaoFu" table="t_xiaofu2">        <id name="id" column="xiaofu_id"> <!-- 设置主键 -->            <generator  column="stu_name" />           </class></hibernate-mapping>
?

?

junit测试:

?

??package endual.bean2;

import java.util.List;import org.hibernate.Query;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import com.iteye.endual.bean2.Student;import com.iteye.endual.bean2.XiaoFu;import util.HibernateUtil;import junit.framework.TestCase;public class TestHibernate extends TestCase {/** * 对个实体bean的存储 */public void test1 () {SessionFactory sf = HibernateUtil.getSessionFactory() ;Session session = sf.openSession() ;XiaoFu xf = new XiaoFu() ;//xf.setId(id)xf.setOwername("chenwei");Student st = new Student() ;st.setName("chenwei");st.setNum(123456) ;st.setXf(xf) ;session.save(st) ;Transaction tr = session.beginTransaction() ;tr.commit() ;//System.out.println(pp.getCard().getIdnum());}}
?

测试结果:

?

? ? 生成了两张表:(见插入,其他学生表中多了一个外键的字段)

?

?

?

1. session.save(st) ; //保存st,也保存了xf,他们的级联是all. 成功

?

?

? ? 2. session.save(xf) ;

?

? ? ? ? session.save(st) ; //成功

? ? 3. session.save(st) ; //成功

? ? ? ? session.save(xf) ;

?

? ? 4.session.save(xf) ; ?//只插入了校服

?

? ? 增加查找和删除修改和级联的设置有很大的关系

?

?

========================================================

?

第二种方式就是主键关联,我们知道主键的值是唯一的,那么我们将两个表的主键的值是一样的,就可以了嘛。

?

我们用学生表的主键的值用的是校服表的主键。

这样我们查询学生的时候,就能查到校服的主键,而根据校服的主键我们就能查到校服的信息了。

?

上代码:

学生表的主键的生成的不能是递增了,我们要用到forein的策略。两张表的字段没有多出来,也只生成两张表。

?

学生的配置文件:

?

?

<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping >    <class name="com.iteye.endual.bean3.Student" table="t_stu3">        <id name="id" column="stu_id"> <!-- 设置主键 -->            <generator column="stu_name" />              <!--  <one-to-one name="card" foreign-key="idx" >                </one-to-one>-->                <one-to-one name="xf" cascade="all"  constrained="true"></one-to-one>    </class></hibernate-mapping>
?

?

?

<id name="id" column="stu_id"> <!-- 设置主键 -->            <generator name="code">package endual.bean3;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import com.iteye.endual.bean3.Student;import com.iteye.endual.bean3.XiaoFu;import util.HibernateUtil;import junit.framework.TestCase;public class TestHibernate extends TestCase {/** * 对个实体bean的存储 */public void test1 () {SessionFactory sf = HibernateUtil.getSessionFactory() ;Session session = sf.openSession() ;XiaoFu xf = new XiaoFu() ;xf.setOwername("chenwei");//xf.setId(4) ;Student st = new Student() ;st.setName("chenwei");st.setNum(123456) ;st.setId(7);st.setXf(xf) ;session.save(st) ;Transaction tr = session.beginTransaction() ;tr.commit() ;}}
?

?

?

测试结果:生成了两种张表(见插图)

?

测试:

??1.?session.save(st) ;?//成功,两个表都插入了

?

? 2.?session.save(xf) ; //很显然值插入了一个校服表

?

? 3.session.save(xf) ;

session.save(st) ; //两个表都插入了,而且值插入一条的

?

? 4. ?session.save(st) ;

session.save(xf) ; //两个表都插入了,而且只插入了一条的

?

居然的各自负责测试举例要看情况了

?

?

---------------------------------------------------

?

下面来到了我们的第三中方法,那就是再创建一张表,通过这个来创建单向的连接

?

我们这表是框架自动会建立的,我们在学生配置文件中设置改表的字段已经名字。

表中放的学生表的主键和校服表的主键,这样我们查找学生的时候,能查到主键,

查到主键,我们在这种表中能查找校服表的主键,这样就能通过校服表的主键,查到校服的信息了。

思路是这样的。

?

配置文件是:

?

student的配置文件

?

?

<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping >    <class name="com.iteye.endual.bean1.Student" table="t_stu1">        <id name="id" column="stu_id"> <!-- 设置主键 -->            <generator column="stu_name" />              <!--  <one-to-one name="card" foreign-key="idx" >                </one-to-one>-->                <join table="join_stu_xf1">               <key column="xf_id"></key>        <!-- 一对一 是 多对一的 一个特殊情况 -->        <many-to-one name="xf"  unique="true" cascade="all"></many-to-one>        </join>    </class></hibernate-mapping>
?

?

?

 <join table="join_stu_xf1"> 校服表的名字,字段是自动生成,也可以自己设置的

?

?

? ?测试类:

?

? ?package endual.bean1;

import java.util.List;import org.hibernate.Query;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import com.iteye.endual.bean1.Student;import com.iteye.endual.bean1.XiaoFu;import util.HibernateUtil;import junit.framework.TestCase;public class TestHibernate extends TestCase {/** * 对个实体bean的存储 */public void test1 () {SessionFactory sf = HibernateUtil.getSessionFactory() ;Session session = sf.openSession() ;XiaoFu xf = new XiaoFu() ;xf.setOwername("chenwei");Student st = new Student() ;st.setName("chenwei");st.setNum(123456) ;st.setXf(xf) ;session.save(st) ;Transaction tr = session.beginTransaction() ;tr.commit() ;session.close() ;}public void test3 () {SessionFactory sf = HibernateUtil.getSessionFactory() ;Session session = sf.openSession() ;        String hql = "from Student as stu where stu.id=?" ;                Query query = session.createQuery(hql) ;        query.setInteger(0, 1) ;                List<Student> lists = query.list() ;        Student stu = lists.get(0) ;                System.out.println(stu.getName());        //用到了才会去查询的        System.out.println(stu.getXf().getOwername());//Transaction tr = session.beginTransaction() ;//tr.commit() ;//System.out.println(pp.getCard().getIdnum());}}
?

?

测试结果,生成了三张表:

1.session.save(stu); 成功插入三个表都有数据

?

2.session.save(xf) ; //失败

?

3.session.save(xf) ;

? ? ? ?session.save(st) ; //成功

?

4.session.save(st) ;

session.save(xf) ; //成功

?

?

------------------------

?

以上是三个方法的代码?

?

有一个点我搞不清楚的是,单向连接啊,这箭头是指向的是学生呢还是校服呢 ?呵呵。

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

读书人网 >开源软件

热点推荐