SSH笔记-Hibernate的映射文件配置

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_22778717/article/details/79954462

1、分为三部分 ①基础配置参数使用 ②多对一映射 ③一对多映射

2、第一点中说的三部分,分别对应包:
①com.demo.sshtest ②com.demossh2 ③com.demo.sshtest3

3、对应代码
————————第一部分 start————————
直接上代码,注释都写到Info.hbm.xml里面

1、Info.java 模型类

package com.demo.sshtest;

import java.util.Date;

import java.sql.Blob;

public class Info {

    public Integer id;
    public String name;
    public String pswd;
    public String description;

    public Date date;
    //长文本
    public String content;
    //二进制数据
    public Blob image;

    public DetailInfo detailInfo;

    public DetailInfo getDetailInfo() {
        return detailInfo;
    }
    public void setDetailInfo(DetailInfo detailInfo) {
        this.detailInfo = detailInfo;
    }

    public Date getDate() {
        return date;
    }
    public void setDate(Date date) {
        this.date = date;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
    public Blob getImage() {
        return image;
    }
    public void setImage(Blob image) {
        this.image = image;
    }

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPswd() {
        return pswd;
    }
    public void setPswd(String pswd) {
        this.pswd = pswd;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }

    public Info(){}
    public Info(String name, String pswd, String description) {
        super();
        this.name = name;
        this.pswd = pswd;
        this.description = description;
    }
    public Info(Integer id,String name, String pswd, String description) {
        super();
        this.id = id;
        this.name = name;
        this.pswd = pswd;
        this.description = description;
    }
    @Override
    public String toString() {
        return "Info [id=" + id + ", name=" + name + ", pswd=" + pswd + ", description=" + description + "]";
    }

}

2、InfoDeatil.java Info的子模型类

package com.demo.sshtest;

public class DetailInfo {

    public String firstName;
    public String lastName;
    public String age;

    public Info info;

    public Info getInfo() {
        return info;
    }
    public void setInfo(Info info) {
        this.info = info;
    }
    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 getAge() {
        return age;
    }
    public void setAge(String age) {
        this.age = age;
    }

    public DetailInfo(){}
    @Override
    public String toString() {
        return "DetailInfo [firstName=" + firstName + ", lastName=" + lastName + ", age=" + age + ", info=" + info
                + "]";
    }

}

数据表InfoDetail的外键是Info的id参数

3、TestHBMconfig.java 测试效果用的类

package com.demo.sshtest;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Date;

import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.sql.Blob;

public class TestHBMconfig {

    public SessionFactory sessionFactory;
    public Session session;
    public Transaction transaction;

    @Before
    public  void init(){
        Configuration configuration = new Configuration().configure();
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();
        System.out.println("init");
    }
    @After
    public  void destory(){
        transaction.commit();
        session.close();
        sessionFactory.close();
        System.out.println("destory");
    }
    @Test
    public void test() throws Exception{
        System.out.println("test");
        Info info = new Info();
        DetailInfo detailInfo = new DetailInfo();
        info.setName("test");
        info.setPswd("testtest");
        info.setDescription("testtesttest");
        info.setDate(new Date());
        info.setContent("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");

        InputStream inputStream = new FileInputStream("E:/workspace/SSHnote_HibernateHBMConfig/images/generator.png");
        Blob image = Hibernate.getLobCreator(session).createBlob(inputStream,inputStream.available());
        info.setImage(image);
        System.out.println(info);

        detailInfo.setFirstName("firstname1");
        detailInfo.setLastName("lastname1");
        detailInfo.setAge("11");
        info.setDetailInfo(detailInfo);

        session.save(info);

    }

}

①实例化之后使用set方法给数据模型赋值,最后hibernate就会生成info和infodetail两个表的insert语句,在插入记录之后还会生成对应的update语句,更新infodetail记录的外键值
②这里有个插入长文本和图片的参数,这里跟模型类里面参数类型和关系映射文件的配置有关系,都对对了就能插入数据了

4、Info.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">
<!-- Generated 2018-4-4 16:22:30 by Hibernate Tools 3.5.0.Final -->

<!--
package:简化配置作用,把包名直接写到package里面,那么以后hibernate-mapping里面有多个在相同包下的类的name就可以直接写类名了
-->
<hibernate-mapping package="com.demo.sshtest">
<!--
class下参数:
name:类名
table:数据表名
dynamic-insert:若设置为 true, 表示当保存一个对象时, 会动态生成 insert 语句, insert 语句中仅包含所有取值不为 null 的字段. 默认值为 false
dynamic-update: 若设置为 true, 表示当更新一个对象时, 会动态生成 update 语句, update 语句中仅包含所有取值需要更新的字段. 默认值为 false
select-before-update:设置 Hibernate 在更新某个持久化对象之前是否需要先执行一次查询. 默认值为 false (对游离对象操作时候有用,如果游离对象跟数据库的数据一样就执行update,反之不执行,因为都会执行一次select,所以会降低效率)
剩下的可以去hibernate的文档查看
-->
    <class name="Info" table="INFO" dynamic-update="true">
        <!--
        id标签
        name:持久化类的属性名
        type:属性类型

        column:指定主键的列名
        generator:标识符生成器,指定如何生成主键(主键应该不具备业务含义的,代理主键通常是整型,这样节省空间)

        unsaved-value:若设定了该属性, Hibernate 会通过比较持久化类的 OID 值和该属性值来区分当前持久化类的对象是否为临时对象(就是,如果对象的主键值跟unsaved-value的值一样,hibernate就会认为这个对象是临时对象,执行saveOrUpdate()的时候会直接执行save()操作),默认false

        -->
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <!--
            generator标签
            class:用class指定生成主键的方式,一般用native
                 ①increment:由hibernate以递增方式为代理主键赋值(读取数据表,找到最大的主键值,插入数据时,将之前获取到的最大主键值数+1,赋值给代理主键)
                    适用范围:适用于所有数据库,但因为并发问题,所以只用于单个进程情况,比如测试
                 ②identity:由底层数据库负责生成,则底层数据库要支持自增字段类型,所以Oracle不能用这个,而且主键类型只能是long、int、short类型
                    适用范围:所以支持自增的数据库 如:DB2、MySQL
                 ③sequence:由底层数据库提供的序列生成主键,所以数据库要支持序列,而且主键类型只能是long、int、short类型
                    适用范围:所以支持序列的数据库 如:DB2、Oracle
                    写法:<generator class="sequence">可以自定义</generator>
                 ④hilo:按照hibernate高低算法生成主键,不依赖任何底层数据库,但是主键类型只能是long、int、short类型,不会出现并发问题
                    适用范围:适用所有数据库
                    逻辑:hibernate会生成一个hibernate_unique_key的表,然后找里面next_hi这个字段的值,最后生成出来一个整型的值,用于生成主键
                 ⑤native:根据底层数据库对自动生成主键的支持能力来选择identity、sequence、hilo
                    适用范围:适合跨数据库平台开发使用,但是主键类型只能是long、int、short类型
            -->
            <generator class="native" />
        </id>
        <!--
        property标签
        ①name:属性名
        ②type:属性类型, 如果没有为某个属性显式设定映射类型, Hibernate 会运用反射机制先识别出持久化类的特定属性的 Java 类型, 然后自动使用与之对应的默认的 Hibernate 映射类型
                如:<property name="name" type="java.lang.String"> 可以写成 <property name="name" type="string">
        ③column->name:字段名,这里的column可以写到property标签里面
                如:<property name="name" type="java.lang.String" column="NAME">
        ④access:指定 Hibernate 的默认的属性访问策略。默认值为 property, 即使用 getter, setter 方法来访问属性. 若指定 field, 则 Hibernate 会忽略 getter/setter 方法, 而通过反射访问成员变量
        ⑤unique: 设置是否为该属性所映射的数据列添加唯一约束
        ⑥index: 指定一个字符串的索引名称
        ⑦update:列的值能否被修改,默认true,哪个property里面加了这个,那么这个字段的值就不能被修改了
        ⑧length: 指定该属性所映射数据列的字段的长度
        ⑨formula:设置一个 SQL 表达式, Hibernate 将根据它来计算出派生属性的值(持久化类的有些属性的值必须在运行时通过计算才能得出来, 这种属性称为派生属性),就是写一个自定义内容到sql语句里面,这个自定义内容就是方便写子sql语句
                如:<property name="TestFormula" formula="xxxx">
        ⑩scale: 指定该属性所映射数据列的小数位数, 对 double, float, decimal 等类型的数据列有效
        -->
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="pswd" type="java.lang.String">
            <column name="PSWD" />
        </property>
        <property name="description" type="java.lang.String">
            <column name="DESCRIPTION" />
        </property>
        <!--
        时间日期类型:
            1、因为java.util.Date是java.sql.Date、java.sql.Time、java.sql.Timestamp的父类,而这三个分类对应标准SQL中的DATE, TIME 和 TIMESTAMP类型
            所以在持久化类中,日期参数一定要import java.util.Date,而映射文件中property标签的type就可以是java.util.Date、date、time、timestamp
            2、要注意的是:这里的date、time、timestamp不是java或者标准sql的类型,是hibernate的类型
        -->
        <property name="date" type="java.util.Date">
            <column name="DATE" />
        </property>
        <!--
        长文本类型:
            1、这里长文本用clob这个hibernate映射类型,这个clob就是java.sql.Clob对应的hebernate类型
            2、如果需要精确指定数据库中的字段类型,可以在column中加上sql-type,这个属性的值写数据库的类型名
        -->
        <property name="content">
            <column name="CONTENT" sql-type="MEDIUMTEXT"/>
        </property>
        <property name="image">
            <column name="IMAGE" sql-type="LONGBLOB"/>
        </property>

         <!--
        映射组成关系
        1、component的name是被映射关系模型的名字,class写被映射关系模型的类名
        2、要写parent,parent的name是域模型的名字,就是被映射关系模型里面定义的域模型的名字
        3、用property写被映射关系模型里面的参数和对应数据表要写的列名
        4、DetailInfo是Info类的组成部分,Hibernate里面称之为组件
        5、Info类(域模型)和DetailInfo类(被映射关系模型)都需要互相实例化,不然插入数据库会出现被映射关系模型的数据是null
        -->
        <component name="detailInfo" class="DetailInfo">
            <parent name="info"/>
            <!-- 指定组成关系的参数属性 -->
            <property name="firstName" type="java.lang.String" column="FIRSTNAME"></property>
            <property name="lastName" type="java.lang.String" column="LASTNAME"></property>
            <property name="age" type="java.lang.String" column="AGE"></property>
        </component>

    </class>
</hibernate-mapping>

这一部分的内容的注意事项或者重点都注释里面了

5、映射关系配置文件中负责配置主键生成规则,主键的generator标签里面的class参数值对照表
主键生成规则

6、映射关系中,参数的数据类型对照表
参数的数据类型1参数的数据类型2

7、映射关系中,时间参数类型对照表
时间参数类型

8、映射关系中,长文本参数类型对照表
长文本参数类型
————————第一部分 end————————

————————第二部分 start————————
多对一关系映射(多个userInfo对应一个user) 例如:一个user,可以有多个地址,多个地址都存在userInfo里面
1、User.java “一”端数据模型

package com.demo.sshtest2;

public class User {

    public Integer id;
    public String name;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

}

2、UserInfo.java “多”端数据模型(在“多”端需要配置“一”端的数据对象参数)

package com.demo.sshtest2;

public class UserInfo {

    public Integer infoId;
    public String infoaddress;
    //多那一端的数据模型才需要创建一那一端的对象
    public User user;

    public Integer getInfoId() {
        return infoId;
    }
    public void setInfoId(Integer infoId) {
        this.infoId = infoId;
    }
    public String getInfoaddress() {
        return infoaddress;
    }
    public void setInfoaddress(String infoaddress) {
        this.infoaddress = infoaddress;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }

}

3、User.hbm.xml user数据模型的关系映射

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2018-4-12 13:14:04 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="com.demo.sshtest2.User" table="USER">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
    </class>
</hibernate-mapping>

4、UserInfo.hbm.xml UserInfo数据模型的关系映射

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2018-4-12 13:14:04 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="com.demo.sshtest2.UserInfo" table="USERINFO">
        <id name="infoId" type="java.lang.Integer">
            <column name="INFOID" />
            <generator class="native" />
        </id>
        <property name="infoaddress" type="java.lang.String">
            <column name="INFOADDRESS" />
        </property>
        <many-to-one name="user" class="com.demo.sshtest2.User">
            <column name="USERID" />
        </many-to-one>
    </class>
</hibernate-mapping>

5、TestMany2One.java 测试方法

package com.demo.sshtest2;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestMany2One {

    public SessionFactory sessionFactory;
    public Session session;
    public Transaction transaction;

    @Before
    public  void init(){
        Configuration configuration = new Configuration().configure();
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();
        System.out.println("init");
    }
    @After
    public  void destory(){
        transaction.commit();
        session.close();
        sessionFactory.close();
        System.out.println("destory");
    }

    @Test
    public void test() throws Exception{
        //测试多对一(多个userInfo对应一个user) 例如:一个user,可以有多个地址,多个地址都存在userInfo里面

        /*
        笔记:
        1、就是一个模型对应另外一个模型的多条记录的情况用
        2、“一”那端的数据模型类和*.hbm.xml只需要正常的写参数名和配置参数就好了
        3、“多”那端的数据模型类里面需要写上“一”那端的类对象属性
        4、*.hbm.xml配置的时候,重点配置都在“多”端
        5、“多”端在*.hbm.xml配置“一”端的对象属性时,用many-to-one标签配置
        6、many-to-one标签对应参数:
                        (1)name:“多”端定义的“一”的类对象属性
                        (2)class:“一”端的类路径
                        (3)column name:“多”端数据表的外键,就是“一”端数据表中的主键值
        示例:<many-to-one name="user" class="com.demo.sshtest2.User"><column name="USERID" /></many-to-one>
        */

        System.out.println("test");
        //设置一那一端的数据
        User user = new User();
        user.setName("userName");

        UserInfo userInfo1 = new UserInfo();
        UserInfo userInfo2 = new UserInfo();
        //设置多那一端的数据
        userInfo1.setInfoaddress("address1");
        userInfo2.setInfoaddress("address2");
        //设定关联关系
        userInfo1.setUser(user);
        userInfo2.setUser(user);

        //执行save,一般先执行一那一端的,再执行多那一端的,这样能减少运行的sql数量,因为插入“多”端时,无法确定外键值
        //如:先执行user的save操作在执行userInfo1 userInfo2,的话只需要运行一条,反过来需要运行3条(后面需要update两次userInfo表的数据)
        session.save(user);
        session.save(userInfo1);
        session.save(userInfo2);
    }
    @Test
    public void testquery(){
        System.out.println("testquery");
        UserInfo userInfo = (UserInfo)session.get(UserInfo.class, 1);
        //查询“多”端数据时候会执行一次selce语句
        //当获取“多”端对象时,默认情况下关联的“一”端对象是一个代理对象
        System.out.println("=========================");
        System.out.println("getInfoId:"+userInfo.getInfoId());
        System.out.println("getInfoaddress:"+userInfo.getInfoaddress());
        System.out.println("getId:"+userInfo.getUser().getId());
        System.out.println("getName:"+userInfo.getUser().getName());
        System.out.println("=========================");

        //查询“一”端数据时,如果session被关闭了,默认情况下会抛出LazyInitializationException异常
        User user = (User)session.get(User.class, 1);
        System.out.println("=========================");
        System.out.println("usergetId:"+user.getId());
        System.out.println("usergetName:"+user.getName());
        System.out.println("=========================");
    }
    @Test
    public void testupdate(){
        System.out.println("testupdate");
        UserInfo userInfo = (UserInfo)session.get(UserInfo.class, 1);
        userInfo.setInfoaddress("sdfasdaf");
    }
    @Test
    public void testdelete(){
        System.out.println("testdelete");
        //在不设定级联记录情况下,“一”端记录有被“多”端对象引用时,不能删除“一”端中对应记录,如:UserInfo中有外键userid为1的记录时,删除不了User中id=1的记录
        User user = (User)session.get(User.class, 1);
        session.delete(user);
    }

}

这里session保存之后,只是保存在缓存里面,需要在destory()方法里面的transaction.commit()提交并且执行sql
————————第二部分 end————————

————————第三部分 start————————
一对多(一个Customer对应一个Merchant) 例如:一个Customer,可以到多个Merchant那里买东西
1、Customer.java “一”端数据模型

package com.demo.sshtest3;

import java.util.HashSet;
import java.util.Set;

public class Customer {

    public Integer Id;
    public String cName;

    /*
    1、用集合
    2、声明集合类型时,要使用接口类型,因为hibernate在获取集合类型时,返回的是hibernate的类型的集合类型,而不是java的集合
    3、需要把集合进行初始化,防止空指针异常
     */
    public Set<Merchant>merchant = new HashSet<>();

    public Integer getId() {
        return Id;
    }
    public void setId(Integer id) {
        Id = id;
    }
    public String getcName() {
        return cName;
    }
    public void setcName(String cName) {
        this.cName = cName;
    }
    public Set<Merchant> getMerchant() {
        return merchant;
    }
    public void setMerchant(Set<Merchant> merchant) {
        this.merchant = merchant;
    }

}

2、Merchant.java “多”端数据模型

package com.demo.sshtest3;

public class Merchant {

    public Integer merId;
    public String merName;
    public Integer getMerId() {
        return merId;
    }
    public void setMerId(Integer merId) {
        this.merId = merId;
    }
    public String getMerName() {
        return merName;
    }
    public void setMerName(String merName) {
        this.merName = merName;
    }


}

3、Customer.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">
<!-- Generated 2018-4-12 22:01:32 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="com.demo.sshtest3.Customer" table="CUSTOMER">
        <id name="Id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="cName" type="java.lang.String" access="field">
            <column name="CNAME" />
        </property>
        <!--
        “一”对“多”的属性集合
        table:“一”的数据表名
        key:外键名
        one-to-many class:需要映射的模型,即“多”的数据模型类名
        -->
        <!--
        双向“一”对“多”的时候:
        set:映射set类型的属性
        table:set中元素对应记录方在哪个表中,则该需要和“多”对“一”的“多”的那个表的名字一致
        key:制定“多”的表中的外键列名字
        inverse:关联主动(false是主动 true是被动),设置之后会少运行update,可能导致外键没设置
        lazy:预加载
        cascade:设定级联操作
            ①delete:删除“一”端数据时,不会受“多”端的映射关系导致不能删除
            ②save-update:删除“一”端数据时,会清理“多”端对应数据的外键值,把外键值变成null
            ③开发时,不建议使用cascade,建议使用手工方式操作数据库
        order-by:对集合排序,使用这个之后,sql语句会多了排序的条件,注意这里使用的是数据表字段,而不是持久化类的属性名
        -->
        <set name="merchant" table="MERCHANT" lazy="true" cascade="save-update" order-by="ID DESC">
            <key>
                <column name="ID" />
            </key>
            <one-to-many class="com.demo.sshtest3.Merchant" />
        </set>
    </class>
</hibernate-mapping>

4、Merchant.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">
<!-- Generated 2018-4-12 22:02:51 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="com.demo.sshtest3.Merchant" table="MERCHANT">
        <id name="merId" type="java.lang.Integer">
            <column name="MERID" />
            <generator class="native" />
        </id>
        <property name="merName" type="java.lang.String">
            <column name="MERNAME" />
        </property>
    </class>
</hibernate-mapping>

5、TestOne2Many.java 测试类

package com.demo.sshtest3;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestOne2Many {

    public SessionFactory sessionFactory;
    public Session session;
    public Transaction transaction;

    @Before
    public  void init(){
        Configuration configuration = new Configuration().configure();
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();
        System.out.println("init");
    }
    @After
    public  void destory(){
        transaction.commit();
        session.close();
        sessionFactory.close();
        System.out.println("destory");
    }

    @Test
    public void test() throws Exception{
        //测试一对多(一个Customer对应一个Merchant) 例如:一个Customer,可以到多个Merchant那里买东西


        System.out.println("test");
        //设置一那一端的数据
        Customer customer = new Customer();
        customer.setcName("cccName");

        Merchant merchant1 = new Merchant();
        Merchant merchant2 = new Merchant();
        //设置多那一端的数据
        merchant1.setMerName("merchant1");
        merchant2.setMerName("merchant2");
        //设定关联关系
        customer.getMerchant().add(merchant1);
        customer.getMerchant().add(merchant2);

        /*
        1、先保存“一”的一端时:先插入“一”端,后插入“多”端,3条insert 2条update
            因为“一”端和“多”端都维护关联关系,多以多出update
        2、先保存“多”的一端时:先插入“多”端,后插入“一”端,3条insert 4条update
            因为“一”端维护关联关系,所以分别update各update一次,最后总的一起update,最后一次update,才是维护关联关系
        3、为了减少因为维护关系而多运行sql的次数,可以在*.hbm.xml里面配置inverse,inverse=false为主动维护方,inverse=true为被动维护方
        4、没有设置inverse=true情况下,默认两边都维护关系
        5、“一”端set标签设为被动方(inverse=true),有利于改善性能,不会多执行额外的update语句
        6、如果“一”端为主控方:①额外多出update语句 ②无法为外键值添加非空约束
         */

        session.save(customer);
        session.save(merchant1);
        session.save(merchant2);
    }
    @Test
    public void testquery(){
        System.out.println("testquery");
        //对“多”端集合进行延迟加载
        Customer customer = (Customer)session.get(Customer.class,1);
        System.out.println(customer.getcName());
        //返回的“多”端的集合是Hibernate内置集合类型,该类型具有延迟加载和存放带你对象的功能
        System.out.println(customer.getMerchant().getClass());
        //查询“一”端数据时,如果session被关闭了,默认情况下会抛出LazyInitializationException异常
        //session.close();
        System.out.println(customer.getMerchant().size());

    }
    @Test
    public void testupdate(){
        System.out.println("testupdate");
        Customer customer = (Customer)session.get(Customer.class, 1);
        customer.setcName("sdfasdaf");
        //这个是修改“一”关联读取的“多”中的那条记录的下一条
        customer.getMerchant().iterator().next().setMerName("ddddddd");
        //这个是制定修改“多”中的某一条记录
        Merchant merchant = (Merchant)session.get(Merchant.class, 3);
        merchant.setMerName("newmerchantname");
        customer.getMerchant().add(merchant);
    }
    @Test
    public void testdelete(){
        System.out.println("testdelete");
        //在不设定级联记录情况下,“一”端记录有被“多”端对象引用时,不能删除“一”端中对应记录,如:UserInfo中有外键userid为1的记录时,删除不了User中id=1的记录
        Customer customer = (Customer)session.get(Customer.class, 2);
        session.delete(customer);
    }

}

————————第三部分 end————————

4、注意事项:
①多对一:就是多个对象对应一个对象,我们需要在“多”端配置外键,就是在“多”端数据模型里面,创建对应“一”端的对象参数,然后用hibernate插件生成映射关系文件的时候,系统就会自动在“多”端生成一个many-to-one标签(需要在该标签里面column值里面制定外键使用的是“一”端数据库的哪个字段,这个字段最好是整型),到时运行sql语句的时候就会对应为“多”端数据表添加外键了
②一对多:就是一个对象对应多个对象,我们需要在“一”端设置一个对应“多”端的对象集合,集合可以是set、list、map、array数组类型,set的对象是不可重复,所以用set好一点
③多对一、一对多只是使用的时候,数据模型间相对的关系,按需使用即可
④对于单向的多对一、一对多关系,建表时,都是在“多”端添加外键指向“一”端,不同点就是维护关系的不同(谁指向谁)
⑤对于双向的多对一、一对多关系,按需分配就好了,就是要注意,“多”端的外键不要为空,有的时候会出错

5、项目目录
项目目录

6、demo
https://download.csdn.net/download/qq_22778717/10351169

阅读更多

没有更多推荐了,返回首页