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

来源:互联网 发布:中南大学网络登录平台 编辑:程序博客网 时间:2024/05/10 07:21

【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 作为配置文件(适合初学者)

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

    这里写图片描述

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

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

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

    // 实例化 ConfigurationConfiguration 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("");// 打开第二个 SessionSession 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

    //修饰组件属性类@Embeddablepublic 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

    //修饰组件属性类@Embeddablepublic 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 0
    原创粉丝点击