Hibernate容器映射技术

 第十一章 Hibernate容器映射技术

在Hibernate之中所谓的所谓的容器映射技术指的是一种简单的一对多关系,但是这个时候表示多的一方只有一个或两个字段的数据表(不包含外键字段),容器映射技术一共存在五中:set、List、Map、Array、Bag。

11.1、Set映射

如果要想表示出set映射的特点,那么肯定需要两张数据表完成,例如:一个人有多个Email地址,如果说发现采用自定义数据类型的处理很麻烦,那么就可以回归到两张数据表的定义结构上。

范例:数据库创建脚本

-- 使用数据库

USE mldn ;

-- 删除数据表

DROP TABLE email ;

DROP TABLE member ;

-- 创建数据表

CREATE TABLE member(

       mid                VARCHAR(50) ,

       name             VARCHAR(50) ,

       CONSTRAINT pk_mid PRIMARY KEY(mid)

) ;

CREATE TABLE email(

       mid                VARCHAR(50) ,

       title                VARCHAR(200) ,

       CONSTRAINT fk_mid FOREIGN KEY(mid) REFERENCES member(mid) ON DELETE CASCADE

) ;

此时存在了以上的数据表,很明显,每一个人员的email地址是是不可能有重复的,所以此时的映射使用Set集合会更加合适一些。

但是在Myeclipse之中,如果要想创建Hibernate映射,那么是不可能直接通过工具创建的,默认的支持是一对多的支持,所以此处只能够根据member表创建Hibernate映射。

范例:观察Member.java类

package cn.cgj.pojo;

import java.util.HashSet;

import java.util.Set;

@SuppressWarnings("serial")

public class Member implements java.io.Serializable {

    private String mid;

    private String name;

    @SuppressWarnings("rawtypes")

    private Set emails = new HashSet(0);

    public Member() {

    }

    //settergetter

}

虽然在Member类中存在了set集合,但是在Member.hbm.xml文件中发现还不是正常所希望的Set映射。

范例:修改Member.hbm.xml文件

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

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class name="cn.cgj.pojo.Member" table="member" catalog="mldn">

        <id name="mid" type="java.lang.String">

            <column name="mid" length="50" />

            <generator class="assigned"></generator>

        </id>

        <property name="name" type="java.lang.String">

            <column name="name" length="50" />

        </property>

        <set name="emails" table="email" lazy="false">

            <key>

                <column name="mid" length="50" />

            </key>

            <element

              type="cn.cgj.pojo.Email"

              column="title"/>

        </set>

    </class>

</hibernate-mapping>

此时“<set>”配置所表示的含义是,集合之中对应的数据要通过email表取得,而且要与email表中的title字段对应。

范例:测试增加程序(由于版本的问题没有与下一个例子做出区分)

package cn.cgj.test;

import cn.cgj.dbc.HibernateSessionFactory;

import cn.cgj.pojo.Member;

public class MemberTestInsert {

    @SuppressWarnings("unchecked")

    public static void main(String[] args) {

        Member mem = new Member();

        mem.setMid("daguo" + System.currentTimeMillis());

        mem.setName("大国");

        mem.getEmails().add("cgjdreaming@126.com");

        mem.getEmails().add("cgjdreaminghq@126.com");

        mem.getEmails().add("cgjdreamingxs@126.com");

        HibernateSessionFactory.getSession().save(mem);

        HibernateSessionFactory.getSession().beginTransaction().commit();

        HibernateSessionFactory.closeSession();

    }

}

Hibernate:

    insert

    into

        mldn.member

        (name, mid)

    values

        (?, ?)

Hibernate:

    insert

    into

        email

        (mid, title)

    values

        (?, ?)

Hibernate:

    insert

    into

        email

        (mid, title)

    values

        (?, ?)

Hibernate:

    insert

    into

        email

        (mid, title)

    values

        (?, ?)

      等于是现在发现在增加member表数据的同时,email表中的数据也一起被增加了,所以这就实现了一个一对多的操作关系(毕竟表示多的一方表只有一个字段)。

范例:查询数据

package cn.cgj.test;

import cn.cgj.dbc.HibernateSessionFactory;

import cn.cgj.pojo.Member;

public class MemberTestSelectById {

    public static void main(String[] args) {

        Member mem = (Member) HibernateSessionFactory.getSession().get(Member.class, "daguo1456840680489");

        System.out.println(mem);

        HibernateSessionFactory.closeSession();

    }

}

Hibernate:

    select

        member0_.mid as mid0_0_,

        member0_.name as name0_0_

    from

        mldn.member member0_

    where

        member0_.mid=?

Hibernate:

    select

        emails0_.mid as mid0_0_,

        emails0_.title as title0_

    from

        email emails0_

    where

        emails0_.mid=?

大国

[cgjdreaming@126.com, cgjdreamingxs@126.com, cgjdreaminghq@126.com]

通过以上的操作可以发现,出现了延迟加载的异常,通过执行的SQL语句可以发现时间上现在只查询了Member一张表,而后直接关闭而了session,而随后要想显示出全部的email地址的话,就会发现有一个问题:Session没有了。所以自然无法向email表发出一个查询语句。

范例:取消延迟加载

package cn.cgj.test;

import cn.cgj.dbc.HibernateSessionFactory;

import cn.cgj.pojo.Member;

public class MemberTestSelectById {

    public static void main(String[] args) {

        Member mem = (Member) HibernateSessionFactory.getSession().get(Member.class, "daguo1456840680489");

        System.out.println(mem);

        HibernateSessionFactory.closeSession();

    }

}

Hibernate:

    select

        member0_.mid as mid0_0_,

        member0_.name as name0_0_

    from

        mldn.member member0_

    where

        member0_.mid=?

Hibernate:

    select

        emails0_.mid as mid0_0_,

        emails0_.title as title0_

    from

        email emails0_

    where

        emails0_.mid=?

Member [mid=daguo1456840680489, name=大国, emails=[cgjdreaming@126.com, cgjdreamingxs@126.com, cgjdreaminghq@126.com]]

修改完之后再次执行可以发现,在执行查询Member的同时,由于取消了延时加载(立刻加载),所以所有与Member对应的email数据就全部显示出来了,等于是一次查询执行了两个查询任务。

范例:更新数据

package cn.cgj.test;

import cn.cgj.dbc.HibernateSessionFactory;

import cn.cgj.pojo.Member;

public class MemberTestUpdate {

    public static void main(String[] args) {

        Member mem = (Member) HibernateSessionFactory.getSession().get(Member.class, "daguo1456840680489");

        mem.getEmails().add("xiaoxiao@126.com");

        HibernateSessionFactory.getSession().update(mem);  

        HibernateSessionFactory.getSession().beginTransaction().commit();

        HibernateSessionFactory.closeSession();

    }

}

Hibernate:

    select

        member0_.mid as mid0_0_,

        member0_.name as name0_0_

    from

        mldn.member member0_

    where

        member0_.mid=?

Hibernate:

    select

        emails0_.mid as mid0_0_,

        emails0_.title as title0_

    from

        email emails0_

    where

        emails0_.mid=?

Hibernate:

    insert

    into

        email

        (mid, title)

    values

        (?, ?)

由于现在处于持久的状态所以实现了先删除一个指定的,而后在增加一个新的。

范例:如果现在中间变成了游离态

package cn.cgj.test;

import java.util.HashSet;

import java.util.Set;

import cn.cgj.dbc.HibernateSessionFactory;

import cn.cgj.pojo.Member;

public class MemberTestUpdate {

    @SuppressWarnings({ "rawtypes", "unchecked" })

    public static void main(String[] args) {

        Member mem = (Member) HibernateSessionFactory.getSession().get(Member.class, "daguo1456840680489");

        HibernateSessionFactory.closeSession(); //游离态

        Set all = new HashSet(); // 新的Set集合

        all.addAll(mem.getEmails());

        all.add("daguo@126.com");

        mem.setEmails(all); // 改变了整个集合

        HibernateSessionFactory.getSession().update(mem);   // 持久态

        HibernateSessionFactory.getSession().beginTransaction().commit();

        HibernateSessionFactory.closeSession();

    }

}

Hibernate:

    select

        member0_.mid as mid0_0_,

        member0_.name as name0_0_

    from

        mldn.member member0_

    where

        member0_.mid=?

Hibernate:

    select

        emails0_.mid as mid0_0_,

        emails0_.title as title0_

    from

        email emails0_

    where

        emails0_.mid=?

Hibernate:

    update

        mldn.member

    set

        name=?

    where

        mid=?

Hibernate:

    delete

    from

        email

    where

        mid=?

Hibernate:

    insert

    into

        email

        (mid, title)

    values

        (?, ?)

Hibernate:

    insert

    into

        email

        (mid, title)

    values

        (?, ?)

Hibernate:

    insert

    into

        email

        (mid, title)

    values

        (?, ?)

Hibernate:

    insert

    into

        email

        (mid, title)

    values

        (?, ?)

Hibernate:

    insert

    into

        email

        (mid, title)

    values

        (?, ?)

发现如果此时游离态中的数据被重新填充集合的话,那么Hibernate之中会自动先执行一删除全部数据的操作,而后在执行填充新数据的操作,而这种做法也是在实际开发之中最为常见的一种形式。

范例:删除操作

package cn.cgj.test;

import org.hibernate.Query;

import cn.cgj.dbc.HibernateSessionFactory;

public class MemberTestSelectDelete {

    public static void main(String[] args) {

        String hql = "DELETE FROM Member As m WHERE mid=?";

        Query query= HibernateSessionFactory.getSession().createQuery(hql);

        query.setString(0, "daguo1456840680489");

        System.out.println(query.executeUpdate());

        HibernateSessionFactory.getSession().beginTransaction().commit();

        HibernateSessionFactory.closeSession();

    }

}

Hibernate:

    delete

    from

        mldn.member

    where

        mid=?

1

发现删除数据的时候它只能够删除Member表(主表)数据,但是却不能发出删除子表的数据,所以这个时候子表数据如果要想删除,那么就必须设置级联删除的操作选项。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值