【Java EE (Struts2 + Spring + Hibernate)开发】:Hibernate(一)基本用法

13 篇文章 0 订阅

【Java EE (Struts2 + Spring + Hibernate)开发】:Hibernate(一)基本用法
本文地址:http://blog.csdn.net/shanglianlm/article/details/49975515

1 ORM 和 Hibernate

1-1 对象/关系数据库映射(ORM)

这里写图片描述
这里写图片描述

1-2 基本映射方式

这里写图片描述
这里写图片描述

1-3 Hibernate 概述

这里写图片描述

2 Hibernate 入门

2-1 Hibernate 下载和安装


  1. 等录 http://www.hibernate.org/downloads 下载 Core 包。
  2. 解压缩,得到如下文件结构

这里写图片描述
这里写图片描述

  • 把 hibernate3.jar 和 lib 目录下的所有 JAR 包添加到应用的类加载路径下。

  • 这里写图片描述

2-2 Hibernate 的数据库操作

News.java

public class News
{
    //消息类的标识属性
    private Integer id;
    //消息标题
    private String title;
    //消息内容
    private String content;

    //id属性的setter和getter方法
    public void setId(Integer id)
    {
        this.id = id;
    }
    public Integer getId()
    {
        return this.id;
    }

    //title属性的setter和getter方法
    public void setTitle(String title)
    {
        this.title = title;
    }
    public String getTitle()
    {
        return this.title;
    }

    //content属性的setter和getter方法
    public void setContent(String content)
    {
        this.content = content;
    }
    public String getContent()
    {
        return this.content;
    }
}

News.hbm.xml

<?xml version="1.0" encoding="gb2312"?>
<!-- 指定Hiberante3映射文件的DTD信息 -->
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- hibernate-mapping是映射文件的根元素 -->
<hibernate-mapping package="org.crazyit.app.domain">
    <!-- 每个class元素对应一个持久化对象 -->
    <class name="News" table="news_table">
        <!-- id元素定义持久化类的标识属性 -->
        <id name="id">
            <!-- 指定主键生成策略 -->
            <generator class="identity"/>
        </id>
        <!-- property元素定义常规属性 -->
        <property name="title"/>
        <property name="content"/>
    </class>
</hibernate-mapping>

PO = POJO + 映射文件

hibernate.cfg.xml

<?xml version="1.0" encoding="GBK"?>
<!-- 指定Hibernate配置文件的DTD信息 -->
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- hibernate- configuration是连接配置文件的根元素 -->
<hibernate-configuration>
    <session-factory>
        <!-- 指定连接数据库所用的驱动 -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <!-- 指定连接数据库的url,hibernate连接的数据库名 -->
        <property name="connection.url">jdbc:mysql://localhost/hibernate</property>
        <!-- 指定连接数据库的用户名 -->
        <property name="connection.username">root</property>
        <!-- 指定连接数据库的密码 -->
        <property name="connection.password">32147</property>
        <!-- 指定连接池里最大连接数 -->
        <property name="hibernate.c3p0.max_size">20</property>
        <!-- 指定连接池里最小连接数 -->
        <property name="hibernate.c3p0.min_size">1</property>
        <!-- 指定连接池里连接的超时时长 -->
        <property name="hibernate.c3p0.timeout">5000</property>
        <!-- 指定连接池里最大缓存多少个Statement对象 -->
        <property name="hibernate.c3p0.max_statements">100</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>
        <property name="hibernate.c3p0.acquire_increment">2</property>
        <property name="hibernate.c3p0.validate">true</property>
        <!-- 指定数据库方言 -->
        <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
        <!-- 根据需要自动创建数据表 -->
        <property name="hbm2ddl.auto">update</property>
        <!-- 显示Hibernate持久化操作所生成的SQL -->
        <property name="show_sql">true</property>
        <!-- 将SQL脚本进行格式化后再输出 -->
        <property name="hibernate.format_sql">true</property>
        <!-- 罗列所有的映射文件 -->
        <mapping resource="org/crazyit/app/domain/News.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

这里写图片描述

NewsManager.java

public class NewsManager
{
    public static void main(String[] args)
        throws Exception
    {
        //实例化Configuration,
        Configuration conf = new Configuration()
        //下面方法默认加载hibernate.cfg.xml文件
            .configure();
        //以Configuration创建SessionFactory
        SessionFactory sf = conf.buildSessionFactory();
        //创建Session
        Session sess = sf.openSession();
        //开始事务
        Transaction tx = sess.beginTransaction();
        //创建消息实例
        News n = new News();
        //设置消息标题和消息内容
        n.setTitle("疯狂Java联盟成立了");
        n.setContent("疯狂Java联盟成立了,"
            + "网站地址http://www.crazyit.org");
        //保存消息
        sess.save(n);
        //提交事务
        tx.commit();
        //关闭Session
        sess.close();
        sf.close();
    }
}

这里写图片描述

使用 Hibernata 进行持久化操作步骤:

这里写图片描述

PO 有三种状态:

这里写图片描述

3 Hibernate 的体系结构

这里写图片描述

4 深入 Hibernate 的配置文件

这里写图片描述

4-1 创建 Configuration 对象

这里写图片描述

4-1-1 使用 hibernate.properties 作为配置文件(适合初学者)

// 实例化 Configuration
Configuration cfg = new Configuration()
     //多次调用 addResource 方法,添加映射文件
     .addResource("Item.hbm.xml")
     .addResource("Bid.hbm.xml");

这里写图片描述

也可以通过向 Configuration 对象添加持久化类,让 Hibernate 自己搜索映射文件:

// 实例化 Configuration
Configuration cfg = new Configuration()
     //多次调用 addClass 方法,直接添加持久化类
     .addClass("lee.Item.class")
     .addClass("lee.Bid.class");

4-1-2 使用 hibernate.cfg.xml 作为配置文件

// 实例化 Configuration
Configuration cfg = new Configuration()
     //configure()方法将会负责加载 hibernate.cfg.xml 文件
     .configure();

这里写图片描述

4-1-3 不使用配置文件创建 Configuration 实例(极度烦琐)

Configuration 对象提供了如下三个方法:
这里写图片描述
利用上面三个方法,可以无须任何配置文件支持,直接通过编程方式创建 Configuration 实例。
NewsManager.java

public class NewsManager
{
    public static void main(String[] args) throws Exception
    {
        //实例化Configuration,不加载任何配置文件
        Configuration conf = new Configuration()
            //通过addClass方法添加持久化类
            .addClass(org.crazyit.app.domain.News.class)
            //通过setProperty设置Hibernate的连接属性。
            .setProperty("hibernate.connection.driver_class" , "com.mysql.jdbc.Driver")
            .setProperty("hibernate.connection.url" , "jdbc:mysql://localhost/hibernate")
            .setProperty("hibernate.connection.username" , "root")
            .setProperty("hibernate.connection.password" , "32147")
            .setProperty("hibernate.c3p0.max_size" , "20")
            .setProperty("hibernate.c3p0.min_size" , "1")
            .setProperty("hibernate.c3p0.timeout" , "5000")
            .setProperty("hibernate.c3p0.max_statements" , "100")
            .setProperty("hibernate.c3p0.idle_test_period" , "3000")
            .setProperty("hibernate.c3p0.acquire_increment" , "2")
            .setProperty("hibernate.c3p0.validate" , "true")
            .setProperty("hibernate.dialect" , "org.hibernate.dialect.MySQLInnoDBDialect")
            .setProperty("hibernate.hbm2ddl.auto" , "create");
        //以Configuration创建SessionFactory
        SessionFactory sf = conf.buildSessionFactory();
        //实例化Session
        Session sess = sf.openSession();
        //开始事务
        Transaction tx = sess.beginTransaction();
        //创建消息实例
        News n = new News();
        //设置消息标题和消息内容
        n.setTitle("疯狂Java联盟成立了");
        n.setContent("疯狂Java联盟成立了,"
            + "网站地址http://www.crazyit.org");
        //保存消息
        sess.save(n);
        //提交事务
        tx.commit();
        //关闭Session
        sess.close();
    }
}

4-2 hibernate.properties 文件与 hibernate.cfg.xml 文件

hibernate.properties

//指定数据库的方言
hibernate.dialect org.hibernate.dialect.MySQLDialect

hibernate.cfg.xml

<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>

格式不同,但其实质完全一样。

4-3 JDBC 连接属性

这里写图片描述
这里写图片描述

下面是配置 C3P0 连接池的配置片段

        <!-- 指定连接数据库所用的驱动 -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <!-- 指定连接数据库的url,hibernate连接的数据库名 -->
        <property name="connection.url">jdbc:mysql://localhost/hibernate</property>
        <!-- 指定连接数据库的用户名 -->
        <property name="connection.username">root</property>
        <!-- 指定连接数据库的密码 -->
        <property name="connection.password">32147</property>
        <!-- 指定连接池里最大连接数 -->
        <property name="hibernate.c3p0.max_size">20</property>
        <!-- 指定连接池里最小连接数 -->
        <property name="hibernate.c3p0.min_size">1</property>
        <!-- 指定连接池里连接的超时时长 -->
        <property name="hibernate.c3p0.timeout">1800</property>
        <!-- 指定连接池里最大缓存多少个Statement对象 -->
        <property name="hibernate.c3p0.max_statements">50</property>

4-4 数据库方言

这里写图片描述
这里写图片描述

4-5 JNDI 连接源的连接属性

这里写图片描述
这里写图片描述

下面是配置 hibernate 连接 Tomcat 中数据源的配置片段。

<!-- 配置 JNDI 数据源的 JNDI 名 -->
<property name="connection.datasource">java:comp/env/jdbc/dstest</property>
<!-- 配置连接数据库的方言 -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>

4-6 Hibernate 事务属性

这里写图片描述
这里写图片描述

4-7 二级缓存相关属性

这里写图片描述

4-8 外连接抓取属性

这里写图片描述

4-9 其他常用的配置属性

这里写图片描述
这里写图片描述

5 深入理解持久化对象

5-1 持久化类的要求

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

5-2 持久化对象的状态

这里写图片描述
这里写图片描述

5-3 改变持久化对象状态的方法

这里写图片描述

//创建消息实例
News n = new News();
//设置消息标题和消息内容
n.setTitle("疯狂java联盟");
n.setContent("疯狂java联盟成立了," + "http://www.aaa.com");
//保存消息
sess.save(n);

这里写图片描述

这里写图片描述

News n = sess.load(News.class, new Integer(pk));

这里写图片描述
这里写图片描述
这里写图片描述

这里写图片描述

News n = firstSess.load(News.class, new Integer(pk));
// 第一个 Session 已经关闭了
firstSess.close();
// 修改托管状态下的持久化对象
n.setTitle("");
// 打开第二个 Session
Session secondSess = ...
// 保存托管对象所做的修改
secondSess.update(n);

这里写图片描述

还可以通过 Session 的 delete 方法来删除持久化实例,一旦删除了持久化实例,该持久化实例对应的数据记录也将被删除。

News n = Session.load(News.class, new Integer(pk));
Session.delete(n);

6 深入 Hibernate 的映射文件

6-1 映射文件结构

这里写图片描述

<hibernate-mapping>
         <class />
         <class />
         ...
</hibernate-mapping>

这里写图片描述
这里写图片描述
这里写图片描述

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

6-2 映射主键

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

示例

<class name="News" table="news_table">
   <!-- 定义标识属性 -->
   <id name="id" column="news_id">
     <!-- 定义主键生成器 -->
     <generator class="identity" />
   </id>
   <!-- 用于定义普通属性 -->
   <property ... />
   <property ... />
</class>

6-3 映射普通属性

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

示例:formula
News.java

public class News
{
    //消息类的标识属性
    private Integer id;
    //消息标题
    private String title;
    //消息内容
    private String content;
    //消息全部内容,由系统根据公式生成
    private String fullContent;
    ...
}

News.hbm.xml

<!-- hibernate-mapping是映射文件的根元素 -->
<hibernate-mapping package="org.crazyit.app.domain">
    <!-- 每个class元素对应一个持久化对象 -->
    <class name="News" table="news_table">
        <!-- id元素定义持久化类的标识属性 -->
        <id name="id">
            <generator class="identity"/>
        </id>
        <!-- property元素定义常规属性 -->
        <property name="title" not-null="true"/>
        <property name="content"/>
        <!-- 通过formula指定该属性值没有对应的实际数据列,该属性值将由系统根据表达式来生成-->
        <property name="fullContent"
             formula="(select concat(nt.title,nt.content) 
             from news_table nt where nt.id= id)"/> 
    </class>
</hibernate-mapping>

NewsManager.java

public class NewsManager
{
    public static void main(String[] args) throws Exception
    {
        //实例化Configuration,这行代码默认加载hibernate.cfg.xml文件
        Configuration conf = new Configuration().configure();
        //以Configuration创建SessionFactory
        SessionFactory sf = conf.buildSessionFactory();
        //实例化Session
        Session sess = sf.openSession();
        //开始事务
        Transaction tx = sess.beginTransaction();
//      //创建消息实例
//      News n = new News();
//      //设置消息标题和消息内容
//      n.setTitle("疯狂Java联盟成立了");
//      n.setContent("疯狂Java联盟成立了,"
//          + "网站地址http://www.crazyit.org");
//      //保存消息
//      sess.save(n);
        News n2 = (News)sess.get(News.class , 1);
        //输出fullContent属性值
        System.out.println(n2.getFullContent());
        //提交事务
        tx.commit();
        //关闭Session
        sess.close();
    }
}

这里写图片描述

示例: fullContent 属性值由数据库系统生成。
News.hbm.xml

<!-- hibernate-mapping是映射文件的根元素 -->
<hibernate-mapping package="org.crazyit.app.domain">
    <!-- 每个class元素对应一个持久化对象 -->
    <class name="News" table="news_table">
        <!-- id元素定义持久化类的标识属性 -->
        <id name="id">
            <generator class="identity"/>
        </id>
        <!-- property元素定义常规属性 -->
        <property name="title" not-null="true"/>
        <property name="content"/>
        <!-- 为该property指定generated属性为always
            该属性的值由数据库生成,
            而Hibernate会在每次插入、更新之后执行
            select语句来查询到该属性的值 -->
        <property name="fullContent" 
            column="full_content" type="string"
            generated="insert"/>
    </class>
</hibernate-mapping>

sql.sql

drop database hibernate;
create database hibernate;
use hibernate;
create table news_table
(
id int auto_increment primary key,
title varchar(255) not null,
content varchar(255),
full_content varchar(255)
);
DELIMITER |
create trigger t_full_content_gen BEFORE INSERT ON news_table
    FOR EACH ROW BEGIN
        set new.full_content=concat(new.title,new.content);
    END;
|
DELIMITER ;

NewsManager.java

public static void main(String[] args) throws Exception
    {
        //实例化Configuration,这行代码默认加载hibernate.cfg.xml文件
        Configuration conf = new Configuration().configure();
        //以Configuration创建SessionFactory
        SessionFactory sf = conf.buildSessionFactory();
        //实例化Session
        Session sess = sf.openSession();
        //开始事务
        Transaction tx = sess.beginTransaction();
        //创建消息实例
        News n = new News();
        //设置消息标题和消息内容
        n.setTitle("疯狂Java联盟成立了");
        n.setContent("疯狂Java联盟成立了,"
            + "网站地址http://www.crazyit.org");
        //保存消息
        sess.save(n);
        //输出fullContent属性,将看到title和content连缀的字符串
        System.out.println(n.getFullContent());
        //提交事务
        tx.commit();
        //关闭Session
        sess.close();
    }

6-4 映射集合属性

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

6-4-1 List 集合属性

这里写图片描述

Person.java

public class Person
{
    //标识属性
    private Integer id;
    //普通属性name
    private String name;
    //普通属性age
    private int age;
    //集合属性,保留该对象关联的学校
    private List<String> schools = new ArrayList<String>();
    ...
    //schools属性的setter和getter方法
    public void setSchools(List<String> schools)
    {
        this.schools = schools;
    }
    public List<String> getSchools()
    {
        return this.schools;
    }
}

这里写图片描述
这里写图片描述

Person.hbm.xml

<hibernate-mapping package="org.crazyit.app.domain">
    <class name="Person" table="person_inf">
        <!-- 映射标识属性 -->
        <id name="id" column="person_id">
            <!-- 指定主键生成器策略 -->
            <generator class="identity"/>
        </id>
        <!-- 映射普通属性 -->
        <property name="name" type="string"/>
        <property name="age" type="int"/>
        <!-- 映射List集合属性 -->
        <list name="schools" table="school">
            <!-- 映射集合属性数据表的外键列 -->
            <key column="person_id" not-null="true"/>
            <!-- 映射集合属性数据表的集合索引列 -->
            <list-index column="list_order"/>
            <!-- 映射保存集合元素的数据列 -->
            <element type="string" column="school_name"/>
        </list>
    </class>
</hibernate-mapping>

PersonManager.java

public class PersonManager
{
    public static void main(String[] args)
    {
        PersonManager mgr = new PersonManager();
        mgr.createAndStorePerson();
        HibernateUtil.sessionFactory.close();
    }
    //创建并保存Person对象
    private void createAndStorePerson()
    {
        //打开线程安全的session对象
        Session session = HibernateUtil.currentSession();
        //打开事务
        Transaction tx = session.beginTransaction();
        //创建Person对象
        Person yeeku = new Person();
        //为Person对象设置属性
        yeeku.setAge(29);
        yeeku.setName("crazyit.org");
        //创建List集合
        List<String> schools = new ArrayList<String>();
        schools.add("小学");
        schools.add("中学");
        //设置List集合属性
        yeeku.setSchools(schools);
        session.save(yeeku);
        tx.commit();
        HibernateUtil.closeSession();
    }
}

HibernateUtil.java

package lee;

import org.hibernate.*;
import org.hibernate.cfg.*;

public class HibernateUtil
{
    public static final SessionFactory sessionFactory;

    static
    {
        try
        {
            //采用默认的hibernate.cfg.xml来启动一个Configuration的实例
            Configuration configuration = new Configuration()
                .configure();
            //由Configuration的实例来创建一个SessionFactory实例
            sessionFactory = configuration.buildSessionFactory();
        }
        catch (Throwable ex)
        {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    //ThreadLocal可以隔离多个线程的数据共享,因此不再需要对线程同步  
    public static final ThreadLocal<Session> session
        = new ThreadLocal<Session>();

    public static Session currentSession()
        throws HibernateException
    {
        Session s = session.get();
        //如果该线程还没有Session,则创建一个新的Session
        if (s == null)
        {
            s = sessionFactory.openSession();
            //将获得的Session变量存储在ThreadLocal变量session里
            session.set(s);
        }
        return s;
    }

    public static void closeSession()
        throws HibernateException 
    {
        Session s = session.get();
        if (s != null)
            s.close();
        session.set(null);
    }
}

6-4-2 数组属性

Person.java

public class Person
{
    ...
    //数组属性,保留该对象关联的学校
    private String[] schools;
    ...
    //schools属性的setter和getter方法
    public void setSchools(String[] schools)
    {
        this.schools = schools;
    }
    public String[] getSchools()
    {
        return this.schools;
    }
}

Person.hbm.xml

<hibernate-mapping package="org.crazyit.app.domain">
    <class name="Person" table="person_inf">
        ...
        <!-- 映射数组属性 -->
        <array name="schools" table="school">
            <!-- 映射数组属性数据表的外键列 -->
            <key column="person_id" not-null="true"/>
            <!-- 映射数组属性数据表的数组索引列 -->
            <list-index column="list_order"/>
            <!-- 映射保存数组元素的数据列 -->
            <element type="string" column="school_name"/>
        </array>
    </class>
</hibernate-mapping>

6-4-3 Set 集合属性

这里写图片描述
Person.java

public class Person
{
    ...
    //集合属性,保留该对象关联的学校
    private Set<String> schools = new HashSet<String>();
    ...
    //schools属性的setter和getter方法
    public void setSchools(Set<String> schools)
    {
        this.schools = schools;
    }
    public Set<String> getSchools()
    {
        return this.schools;
    }
}

Person.hbm.xml

<hibernate-mapping package="org.crazyit.app.domain">
    <class name="Person" table="person_inf">
        ...
        <!-- 映射Set集合属性 -->
        <set name="schools" table="school">
            <!-- 映射集合属性数据表的外键列 -->
            <key column="person_id" not-null="true"/>
            <!-- 映射保存集合元素的数据列,增加非空约束 -->
            <element type="string" column="school_name"
                not-null="true"/>
        </set>
    </class>
</hibernate-mapping>

这里写图片描述

6-4-4 bag 元素映射

这里写图片描述
Person.java

public class Person
{
    ...
    //集合属性,保留该对象关联的学校
    private Collection<String> schools = new ArrayList<String>();
    ...
    //schools属性的setter和getter方法
    public void setSchools(Collection<String> schools)
    {
        this.schools = schools;
    }
    public Collection<String> getSchools()
    {
        return this.schools;
    }
}

Person.hbm.xml

<hibernate-mapping package="org.crazyit.app.domain">
    <class name="Person" table="person_inf">
        ...
        <!-- 使用bag元素映射集合属性 -->
        <bag name="schools" table="school">
            <!-- 映射集合属性数据表的外键列 -->
            <key column="person_id" not-null="true"/>
            <!-- 映射保存集合元素的数据列 -->
            <element type="string" column="school_name"
                not-null="true"/>
        </bag>
    </class>
</hibernate-mapping>

6-4-5 Map 集合属性

这里写图片描述
Person.java

public class Person
{
    ...
    //集合属性,保留该对象关联的考试成绩
    private Map<String ,Float> scores = new HashMap<String ,Float>();
    ...
    //scores属性的setter和getter方法
    public void setScores(Map<String ,Float> scores)
    {
        this.scores = scores;
    }
    public Map<String ,Float> getScores()
    {
        return this.scores;
    }
}

Person.hbm.xml

<hibernate-mapping package="org.crazyit.app.domain">
    <class name="Person" table="person_inf">
        ...
        <!-- 映射Map集合属性 -->
        <map name="scores" table="score">
            <!-- 映射集合属性数据表的外键列 -->
            <key column="person_id" not-null="true"/>
            <!-- 映射集合属性数据表的Map key列 -->
            <map-key column="subject" type="string"/>
            <!-- 映射保存集合元素的数据列 -->
            <element column="grade" type="float"/>
        </map>
    </class>
</hibernate-mapping>

6-5 集合属性的性能分析

这里写图片描述

6-6 有序集合映射

这里写图片描述
Person.java

public class Person
{
    //标识属性
    private Integer id;
    //普通属性name
    private String name;
    //普通属性age
    private int age;
    //有序集合属性,保留该对象参与的培训
    private SortedSet<String> trainings = new TreeSet<String>();
    ...
    //trainings属性的setter和getter方法
    public void setTrainings(SortedSet<String> trainings)
    {
        this.trainings = trainings;
    }
    public SortedSet<String> getTrainings()
    {
        return this.trainings;
    }
}

Person.hbm.xml

<hibernate-mapping package="org.crazyit.app.domain">
    <class name="Person" table="person_inf">
        <!-- 映射标识属性 -->
        <id name="id" column="person_id">
            <!-- 指定主键生成器策略 -->
            <generator class="identity"/>
        </id>
        <!-- 映射普通属性 -->
        <property name="name" type="string"/>
        <property name="age" type="int"/>
        <!-- 映射SortedSet集合属性,使用自然排序
            增加sort="natural"定义-->
        <set name="trainings" table="training"
            sort="natural">
            <!-- 映射集合属性数据表的外键列 -->
            <key column="person_id" not-null="true"/>
            <!-- 映射保存集合元素的数据列,增加非空约束 -->
            <element type="string" column="training_name"
                not-null="true"/>
        </set>
    </class>
</hibernate-mapping>

PersonManager.java

public class PersonManager
{
    public static void main(String[] args)
    {
        PersonManager mgr = new PersonManager();
        mgr.createAndStorePerson();
        HibernateUtil.sessionFactory.close();
    }

    private void createAndStorePerson()
    {
        Session session = HibernateUtil.currentSession();
        Transaction tx = session.beginTransaction();
        //创建Person对象
        Person wawa = new Person();
        //为Person对象设置属性
        wawa.setAge(21);
        wawa.setName("crazyit.org");
        //创建Set集合
        SortedSet<String> s = new TreeSet<String>();
        s.add("Wild Java Camp");
        s.add("Sun SCJP");
        //设置Set集合属性
        wawa.setTrainings(s);
        session.save(wawa);
        tx.commit();
        HibernateUtil.closeSession();
    }
}

这里写图片描述

Person p = (Person)session.get(Person.class , 1);
p.getTrainings().add("CCNP");

这里写图片描述

<!-- 映射Set集合属性,指定在内存中排序 -->
<set name="trainings" table="training" order-by="training desc">
    <!-- 映射集合属性数据表的外键列 -->
    <key column="person_id" not-null="true"/>
    <!-- 映射保存集合元素的数据列,增加非空约束 -->
    <element type="string" column="training" not-null="true"/>
</set>

这里写图片描述

6-7 映射数据库对象

这里写图片描述
这里写图片描述

News.hbm.xml

<!-- hibernate-mapping是映射文件的根元素 -->
<hibernate-mapping>
    <!-- 使用data-object元素定义数据库对象 -->
    <database-object>
        <!-- 定义创建数据库对象的语句 -->
        <create>create table test(t_name varchar(255));</create>
        <!-- 让drop元素为空,不删除任何对象 -->
        <drop></drop>
        <!-- 指定仅对MySQL数据库有效 -->
        <dialect-scope name="org.hibernate.dialect.MySQLDialect"/>
        <dialect-scope name="org.hibernate.dialect.MySQLInnoDBDialect"/>
    </database-object>  
</hibernate-mapping>

NewsManager.java

        //实例化Configuration,这行代码默认加载hibernate.cfg.xml文件
        Configuration conf = new Configuration().configure();
        //以Configuration创建SessionFactory
        SessionFactory sf = conf.buildSessionFactory();

这里写图片描述

7 映射组件属性

这里写图片描述

Person.java

public class Person
{
    //标识属性
    private Integer id;
    //普通属性age
    private int age;
    //组件属性name
    private Name name;
    ...
    //name属性的setter和getter方法
    public void setName(Name name)
    {
        this.name = name;
    }
    public Name getName()
    {
        return this.name;
    }
}

Name.java

public class Name
{
    //定义first属性
    private String first;
    //定义last属性
    private String last;
    //引用拥有该Name的Person对象
    private Person owner;

    //无参数的构造器
    public Name()
    {
    }
    //初始化first、last属性的构造器
    public Name(String first , String last)
    {
        this.first = first;
        this.last = last;
    }
    ... 
    //owner属性的setter和getter方法
    public void setOwner(Person owner)
    {
        this.owner = owner;
    }
    public Person getOwner()
    {
        return this.owner;
    }
}

这里写图片描述
这里写图片描述
Person.hbm.xml

<hibernate-mapping package="org.crazyit.app.domain">
    <class name="Person" table="person_inf">
        <!-- 映射标识属性 -->
        <id name="id" column="person_id">
            <!-- 指定主键生成器策略 -->
            <generator class="identity"/>
        </id>
        <!-- 映射普通属性 -->
        <property name="age" type="int"/>
        <!-- 映射组件属性name,组件属性的类型为Name -->
        <component name="name" 
            class="Name" unique="true">
            <!-- 指定owner属性代表容器实体 -->
            <parent name="owner"/>
            <!-- 映射组件属性的first属性 -->
            <property name="first"/>
            <!-- 映射组件属性的last属性 -->
            <property name="last"/>
        </component>
    </class>
</hibernate-mapping>

PersonManager.java

public class PersonManager
{
    public static void main(String[] args)
    {
        PersonManager mgr = new PersonManager();
        mgr.createAndStorePerson();
        HibernateUtil.sessionFactory.close();
    }

    private void createAndStorePerson()
    {
        Session session = HibernateUtil.currentSession();
        Transaction tx = session.beginTransaction();
        //创建Person对象
        Person yeeku = new Person();
        //为Person对象设置属性
        yeeku.setAge(29);
        Name n = new Name("crazyit.org" , "疯狂Java联盟");
        yeeku.setName(n);
        session.save(yeeku);
        tx.commit();
        HibernateUtil.closeSession();
    }
}

结果
这里写图片描述

7-1 组合属性为集合

这里写图片描述
Name.java

public class Name
{
    ...
    //引用拥有该Name的Person对象
    private Person owner;
    private Map<String ,Integer> power = new HashMap<String ,Integer>();
    ...
    //power属性的setter和getter方法
    public void setPower(Map<String ,Integer> power)
    {
        this.power = power;
    }
    public Map<String ,Integer> getPower()
    {
        return this.power;
    }
}

Person.hbm.xml

<hibernate-mapping package="org.crazyit.app.domain">
    <class name="Person" table="person_inf">
        <!-- 映射标识属性 -->
        <id name="id" column="person_id">
            <!-- 指定主键生成器策略 -->
            <generator class="identity"/>
        </id>
        <!-- 映射普通属性 -->
        <property name="age" type="int"/>
        <!-- 映射组件属性name,组件属性的类型为Name -->
        <component name="name" 
            class="Name" unique="true">
            <!-- 指定owner属性代表容器实体 -->
            <parent name="owner"/>
            <!-- 映射组件属性的first属性 -->
            <property name="first"/>
            <!-- 映射组件属性的last属性 -->
            <property name="last"/>
            <!-- 映射组件属性里的Map集合属性 -->
            <map name="power" table="name_power">
                <!-- 映射集合属性数据表的外键列 -->
                <key column="person_name_id" not-null="true"/>
                <!-- 映射集合属性数据表的Map key列 -->
                <map-key column="name_aspect" type="string"/>
                <!-- 映射保存集合元素的数据列 -->
                <element column="name_power" type="int"/>
            </map>
        </component>
    </class>
</hibernate-mapping>

7-2 集合属性的元素为组件

这里写图片描述
Person.java

public class Person
{
    ...
    //组件属性name
    private Map<String , Name> nicks = new HashMap<String , Name>();        
    ...
    //nicks属性的setter和getter方法
    public void setNicks(Map<String , Name> nicks)
    {
        this.nicks = nicks;
    }
    public Map<String , Name> getNicks()
    {
        return this.nicks;
    }
}

Person.hbm.xml

<hibernate-mapping package="org.crazyit.app.domain">
    <class name="Person" table="person_inf">
        <!-- 映射标识属性 -->
        <id name="id" column="person_id">
            <!-- 指定主键生成器策略 -->
            <generator class="identity"/>
        </id>
        <!-- 映射普通属性 -->
        <property name="age" type="int"/>
        <!-- 映射nicks集合属性,集合属性对应的数据表为nick_inf -->
        <map name="nicks" table="nick_inf">
            <!-- 映射集合属性数据表的外键列 -->
            <key column="person_id" not-null="true"/>
            <!-- 映射集合属性数据表的Map key列 -->
            <map-key column="phase" type="string"/>
            <!-- 映射保存集合里的组件元素 -->
            <composite-element class="Name">
                <!-- 指定owner属性代表容器实体 -->
                <parent name="owner"/>
                <!-- 映射组件属性的first属性 -->
                <property name="first"/>
                <!-- 映射组件属性的last属性 -->
                <property name="last"/>
            </composite-element>
        </map>
    </class>
</hibernate-mapping>

7-3 组件作为 Map 的索引

这里写图片描述
Person.java

public class Person
{
    ...
    //集合属性nickPower
    private Map<Name , Integer> nickPower = new HashMap<Name , Integer>();
    ... 
    //nickPower属性的setter和getter方法
    public void setNickPower(Map<Name , Integer> nickPower)
    {
        this.nickPower = nickPower;
    }
    public Map<Name , Integer> getNickPower()
    {
        return this.nickPower;
    }
}

Name.java

public class Name
{
    //定义first属性
    private String first;
    //定义last属性
    private String last;
    //引用拥有该Name的Person对象
    private Person owner;

    //无参数的构造器
    public Name()
    {
    }
    //初始化全部属性的构造器
    public Name(String first , String last)
    {
        this.first = first;
        this.last = last;
    }
    ...
    //重写equals方法,根据first、last进行判断
    public boolean equals(Object obj)
    {
        if (this == obj)
        {
            return true;
        }
        if (obj != null 
            && obj.getClass() == Name.class)
        {
            Name target = (Name)obj;
            if (target.getFirst().equals(getFirst())
                && target.getLast().equals(getLast()))
            {
                return true;
            }
        }
        return false;
    }

    //重写hashCode方法,根据first、last计算hashCode值
    public int hashCode()
    {
        return getFirst().hashCode() * 13 
            + getLast().hashCode();
    }
}

Person.hbm.xml

<hibernate-mapping package="org.crazyit.app.domain">
    <class name="Person" table="person_inf">
        <!-- 映射标识属性 -->
        <id name="id" column="person_id">
            <!-- 指定主键生成器策略 -->
            <generator class="identity"/>
        </id>
        <!-- 映射普通属性 -->
        <property name="age" type="int"/>
        <!-- 映射nickPower集合属性,集合属性对应的数据表为nick_power -->
        <map name="nickPower" table="nick_power">
            <!-- 映射集合属性数据表的外键列 -->
            <key column="person_id" not-null="true"/>
            <!-- 映射集合属性数据表的Map key列 ,
                因为Map key的数据类型是复合类型,所以使用如下元素-->
            <composite-map-key class="Name">
                <!-- 映射复合组件的属性 -->
                <key-property name="first" type="string"/>
                <key-property name="last" type="string"/>
            </composite-map-key>
            <!-- 映射集合元素的数据列 -->
            <element column="nick_power" type="int"/>
        </map>
    </class>
</hibernate-mapping>

7-4 组件作为集合主键

这里写图片描述
这里写图片描述
Person.java

public class Person
{
    //以Name组件作为标识属性
    private Name name;
    //普通属性age
    private int age;
    //name属性的setter和getter方法
    public void setName(Name name)
    {
        this.name = name;
    }
    public Name getName()
    {
        return this.name;
    }
    ...
}

Name.java

public class Name
    implements java.io.Serializable
{
    //定义first属性
    private String first;
    //定义last属性
    private String last;    //无参数的构造器
    public Name()
    {
    }
    //初始化全部属性的构造器
    public Name(String first , String last)
    {
        this.first = first;
        this.last = last;
    }   
    ...
    //重写equals方法,根据first、last进行判断
    public boolean equals(Object obj)
    {
        if (this == obj)
        {
            return true;
        }
        if (obj != null 
            && obj.getClass() == Name.class)
        {
            Name target = (Name)obj;
            if (target.getFirst().equals(getFirst())
                && target.getLast().equals(getLast()))
            {
                return true;
            }
        }
        return false;
    }
    //重写hashCode方法,根据first、last计算hashCode值
    public int hashCode()
    {
        return getFirst().hashCode() * 7 
            + getLast().hashCode();
    }
}

Person.hbm.xml

<hibernate-mapping package="org.crazyit.app.domain">
    <class name="Person" table="person_inf">
        <!-- 映射组件类型的标识属性 -->
        <composite-id name="name" class="Name">
            <!-- 映射组件主键里的各属性 -->
            <key-property name="first" type="string"/>
            <key-property name="last" type="string"/>
        </composite-id>
        <!-- 映射普通属性 -->
        <property name="age" type="int"/>
    </class>
</hibernate-mapping>

这里写图片描述
PersonManager.java

public class PersonManager
{
    public static void main(String[] args)
    {
        PersonManager mgr = new PersonManager();
        mgr.createAndStorePerson();
        HibernateUtil.sessionFactory.close();
    }
    private void createAndStorePerson()
    {
        Session session = HibernateUtil.currentSession();
        Transaction tx = session.beginTransaction();
        //创建Person对象
        Person yeeku = new Person();
        //为Person对象设置属性
        yeeku.setAge(29);
        //创建一个Name对象作为Person对象的标识属性值
        Name n = new Name("crazyit.org" , "疯狂Java联盟");
        yeeku.setName(n);
        session.save(yeeku);
        tx.commit();
        HibernateUtil.closeSession();
    }
}

7-5 多列作为联合主键

这里写图片描述
Person.java

public class Person implements java.io.Serializable
{
    //定义first属性,作为标识属性的成员
    private String first;
    //定义last属性,作为标识属性的成员
    private String last;
    //普通属性age
    private int age;
    ...
    //重写equals方法,根据first、last进行判断
    public boolean equals(Object obj)
    {
        if (this == obj)
        {
            return true;
        }
        if (obj != null 
            && obj.getClass() == Person.class)
        {
            Person target = (Person)obj;
            if (target.getFirst().equals(getFirst())
                && target.getLast().equals(getLast()))
            {
                return true;
            }
        }
        return false;
    }

    //重写hashCode方法,根据first、last计算hashCode值
    public int hashCode()
    {
        return getFirst().hashCode() * 13
            + getLast().hashCode();
    }
}

这里写图片描述
Person.hbm.xml

<hibernate-mapping package="org.crazyit.app.domain">
    <class name="Person" table="person_inf">
        <!-- 直接使用composite-id映射多列联合主键 -->
        <composite-id>
            <!-- 映射组件主键里的各属性 -->
            <key-property name="first" type="string"/>
            <key-property name="last" type="string"/>
        </composite-id>
        <!-- 映射普通属性 -->
        <property name="age" type="int"/>
    </class>
</hibernate-mapping>

8 使用 JPA Annotation 标注实体

8-1 增加 JPA Annotation 支持

当采用 来管理实体类之后,可以得到如下公式:

PO = POJO + @Annotation

将 hibernate 发行包 lib 目录下 jpa 子目录下的 JAR 包添加到了系统的类加载路径中。
示例
Person.java

@Entity
@Table(name="person_table")
public class Person
{
    /* 指定使用复合主键类是Name */
    @EmbeddedId
    @AttributeOverrides({
        @AttributeOverride(name="first"
            , column=@Column(name="person_first")),
        @AttributeOverride(name="last"
            , column=@Column(name="person_last" , length=20))
    })
    private Name name;
    //普通属性
    @Column(name="person_email")
    private String email;
    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name="name" 
            , column=@Column(name="cat_name" , length=35)),
        @AttributeOverride(name="color" 
            , column=@Column(name="cat_color"))
    })
    //组件属性,代表此人拥有的宠物
    private Cat pet;
    ...
}

@Entity 标注该类是一个持久化类
@EmbeddedId 标注复合类型的标识属性
@Embedded 标注一个组件属性

Name.java

//修饰组件属性类
@Embeddable
public class Name
    implements java.io.Serializable
{
    private String first;
    private String last;
    //无参数的构造器
    public Name()
    {
    }
    //初始化全部属性的构造器
    public Name(String first , String last)
    {
        this.first = first;
        this.last = last;
    }   
    ...
    //提供重写的equals方法
    public boolean equals(Object obj)
    {
        if (this == obj)
        {
            return true;
        }
        if (obj.getClass() == Name.class)
        {
            Name target = (Name)obj;
            if (target.getFirst().equals(first)
                && target.getLast().equals(last))
            {
                return true;
            }
        }
        return false;
    }

    //提供重写的hashCode方法
    public int hashCode()
    {
        return first.hashCode() + last.hashCode() * 17;
    }
}

Cat.java

//修饰组件属性类
@Embeddable
public class Cat
{
    private String name;
    private String color;

    //无参数的构造器
    public Cat()
    {
    }
    //初始化全部属性的构造器
    public Cat(String name , String color)
    {
        this.name = name;
        this.color = color;
    }
    ...
}

这里写图片描述

hibernate.cfg.xml

<hibernate-configuration>
    <session-factory>
        ...
        <!-- 罗列所有的持久化类 -->
        <mapping class="org.crazyit.app.domain.Person"/>
    </session-factory>
</hibernate-configuration>

8-2 JPA Annotation? 还是 XML 映射文件

这里写图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值