zoukankan      html  css  js  c++  java
  • Hibernate入门4.核心技能

    Hibernate入门4.核心技能 20131128

    代码下载 链接: http://pan.baidu.com/s/1Ccuup 密码: vqlv

    前言:

             前面学习了Hibernate3的基本知识,并且应用在简单的实践中。这些知识Hibernate的基本知识,只能说是会使用简单的hibernate了。这一章学习的是Hibernate的核心技能。主要知识点:

             Hibernate中持久化类的关联关系、Hibernate的批量处理技术、Query接口的核心方法和使用、HQL语言的查询、Criteria接口的核心方法以及查询技巧、Restrictions的使用方法、DetachedCriteria离线查询的技巧、Hibernate事务处理

    1.Hibernate中的关联关系

             关联关系指的是类之间的引用关系,是实体对象之间普遍存在的一种关系。使用Hibernate框架可以完整的表述这种关联关系,如果映射的十分恰当,Hibernate的关联映射将在很大程度上简化对于持久层数据的访问。

    1.1一对多的关联关系

             单项的N-1的关系,只能够从N访问到1的一端,在类与类的各种关联关系中,单项N-1关联和关系数据库中的外检参照关系最为相似。比如Customer和Order,使用的是N-1的单项关联,即从Order到Customer的关联关系。(其实这里已经买下一个地雷了,我们使用Order表示订单,在数据库中,对应的表的名字可以是order,当然是不可以的,因为order是关键字。在数据库的创建表的过程中,我习惯使用小写字母,这里就会出现非常隐蔽的错误,我们不断的调试程序,却始终找不到错误。)

    Customer.java

    package com.yang.hib.model;

    public class Customer {

        private int id;

        private String userName;

        private String password;

        private String realName;

        private String address;

        private String mobile;

        private String email;

       

        public Customer(){}

        public Customer(String userName, String password, String realName,

                String address, String mobile, String email) {}

        //getter & setter

    }

    Order.java:

    package com.yang.hib.model;

    import java.util.Date;

    public class Order {

        private int id;

        private String orderNo;

        private Date date;

        private double total;

        private Customer customer;

       

        public Order(){}

       

        public Order(String orderNo, Date date, double total, Customer customer) {}

        //getter & setter

        public void setCustomer(Customer customer){this.customer = customer;}

        public Customer getCustomer(){return this.customer;}

    }

    Customer.hbm.xml //没有什么特别的地方

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

    <!DOCTYPE hibernate-mapping PUBLIC

        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

    <hibernate-mapping package="com.yang.hib.model">

        <class name="Customer" table="customer">

            <!—参考之前的代码-->

        </class>

    </hibernate-mapping>

    Order.hbm.xml

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

    <!DOCTYPE hibernate-mapping PUBLIC

        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

    <hibernate-mapping package="com.yang.hib.model">

        <class name="Order" table="myorder">

        <!—注意这里的数据表不可以是order,关键字一般情况下不能够用作表名-->

            <id name="id" column="id">

                <generator class="native"/>

            </id>

            <property name="orderNo"    column="orderno"    type="string"/>

            <property name="date"       column="orderdate" type="timestamp"/>

            <property name="total"      column="total"      type="double"/>

            <many-to-one name="customer" column="customer_id" class="Customer" cascade="save-update"/>

            <!—这一句是最为核心的配置信息,实现多对一的级联关系-->

        </class>

    </hibernate-mapping>

    HibernateUtil.java

    package com.yang.hib.util;

    public class HibernateUtil {

       

        private static String HIBERNATE_CONFIG_FILE = "hibernate.cfg.xml";

        private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();

        private static Configuration configuration = new Configuration();

        private static SessionFactory sessionFactory ;

        /*静态代码段,在该类加载的时候,执行这一段代码,这里使用的是单例模式,同时为了在多线程中使用session,使用了线程的局部变量,之前在Java进阶中的关于线程同步的知识中,最后一种方式便是使用的这一种线程局部变量将他保护起来的方式*/

        static{

            try{

                configuration.configure(ClassLoader.getSystemResource(HIBERNATE_CONFIG_FILE));

                sessionFactory = configuration.buildSessionFactory();          

            }catch(Exception e){

                System.err.println("%%%%%Error Creating session factory %%%%%%%%");

                e.printStackTrace();

            }

        }

        //禁止外部创建该类型的对象

        private HibernateUtil(){}

       

        public static Session getSession() throws HibernateException{

            Session session = threadLocal.get();

            if(session == null || !session.isOpen()){

                if(sessionFactory == null){

                    sessionFactory = configuration.buildSessionFactory();

                }

                session = (sessionFactory != null)?sessionFactory.openSession():null;

                threadLocal.set(session);

            }

            return session;

        }

       

        public static void reBuildSessionFactory(){

            try{

                configuration.configure(HIBERNATE_CONFIG_FILE);

                sessionFactory = configuration.buildSessionFactory();

            }catch(Exception e){

                System.err.println("%%%%Error Creating SessionFactory %%%%%");

                e.printStackTrace();

            }

        }

       

        public static void closeSession() throws HibernateException{

            Session session  = threadLocal.get();

            threadLocal.set(null);

            if(session != null){

                session.close();

            }

        }

       

        public static SessionFactory getSessionFactory(){

            return sessionFactory;

        }

       

        public static void setHibernateConfigFile(String hibernateConfigFile){

            HIBERNATE_CONFIG_FILE = hibernateConfigFile;

        }

        public static Configuration getConfiguration(){

            return configuration;

        }

    }

    TeatMain.java

    package com.yang.main;

     

    public class TestMain {

     

        public static void addCustomerAndOrder(){

            Customer customer = new Customer("yang","12345","杨腾飞","广州","15800027127","1076906529@qq.com");

            System.out.println("add customer to database");

            addCustomer(customer);

           

            Order order1 = new Order("A1",new Date(),42.8,customer);

            System.out.println("add order to database");

            addOrder(order1);

            order1 = new Order("A2",new Date(),35.9,customer);

            System.out.println("add antother order to database");

            addOrder(order1);

        }

       

        public static void addCustomer(Customer customer){

            Session session = HibernateUtil.getSession();

            Transaction trans = session.beginTransaction();

            session.save(customer);

            trans.commit();

            HibernateUtil.closeSession();

        }

        public static void addOrder(Order order){

            Session session = HibernateUtil.getSession();

            Transaction trans = session.beginTransaction();

            session.save(order);

            trans.commit();

            HibernateUtil.closeSession();

        }

        public static void main(String[] args) {

            // TODO Auto-generated method stub

            addCustomerAndOrder();

        }

    }

    我们可以根据订单查询出数据库中的对应的顾客的信息,修改TestMain.java函数:

    public static void findOrder(int id){

        Session session = HibernateUtil.getSession();

       

        Order order = (Order) session.get(Order.class, id);

        Customer customer = order.getCustomer();

       

        System.out.println( "Id:"+order.getId()+

                            " total:"  + order.getTotal()+

                            " orderdate:" + order.getDate().toLocaleString() +

                            " realName:"+customer.getRealName()+

                            " mobile:" + customer.getMobile());

        HibernateUtil.closeSession();

    }

    public static void main(String[] args) {

        // TODO Auto-generated method stub

        //addCustomerAndOrder();

        findOrder(1);

    }

    这个时候,我们发现在控制台中是执行了两个SQL语句,对于两个表的查询,我们可以使用连接的形式使用一条SQL语句便可以完成这些查询:

    在hibernate-mapper配置信息中,对于<many-to-one>元素中可以使用指定的属性来让hibernate使用连接的方式:

    <many-to-one name=”customer” fetch=”join” column=”customer_id” class=”Customer”/>实现。对于many-to-one元素的fetch属性也可以使用outer-join属性替代,默认情况之下使用的是fetch=”select”。

    1.2单项的1-N的关系

    Customer与Order就是一对多的关系,我们可以在Order中添加orders集合属性

    Customer.java

    private Set<Order> orders=new HashSet<Order>();

    public void setOrders(Set<Order> orders){ this.orders = orders;}

    public Set<Order> getOrders(){return this.orders;}

    配置文件中添加如下配置信息:

    Customer.hbm.xml

    <set name="orders">

        <key column="customer_id"/><!—这里是对应的另一个表中的字段-->

        <one-to-many class="Order"/>

    </set>

        在Hibernate中通过比较两个持久化对象的标识符属性ID来判断两者是否是相等的,这需要在实体类中对equals()和hashCode()方法重写。

    重写hashCode()

    public int hashCode(){

        final int prime = 31;

        int result = 1;

        result = result*prime + ((id==null)?0:id.hashCode());

        return result;

    }

        也就是将id+prime作为其对象的hashCode

    同时对已比较两个对象是否相等,如果两者的引用是同一个对象的话,那么无论怎样都是相等的,否则如果对象是null的话,那么两者肯定不相等,因为如果两个都是null的话,那么在前面的判断中两者引用都是null则相等。继而继续判断:将obj转换成为目标类型的对象,这个时候原始的对象的id如果是null,也就是数据库中没有该数据,另一个对象也是没有持久化的,内容虽然不相同,但是两者的都没有id,则判断两者是相等的。

    参考代码:

    Customer c1 = new Customer("yssg","12345","sss","广州","sssss","1076sss529@qq.com");

    Customer c2 = new Customer("yanssg","134545","sss","广州","sss7","107sss0ss6529@qq.com");

    System.out.println(c1.equals(c2));

    正常情况之下,两者是不想等的,但是在Hibernate重写equals函数之后,两者就是相等的。很诡异的吧,其实我现在也不是很理解。但是这是在Hibernate中比较数据库中的两个对象,就只会根据id来判断。

    public boolean equals(Object obj){

        if(this == obj){    return true;    }

        if(obj == null){    return false;}

        if(getClass() != obj.getClass()){   return false;}

        Customer other = (Customer) obj;

        if(id == null){

    if(other.id != null){return false;}

        }else if( ! id.equals(other.id)){

            return false;

        }

        return true;

    }

        下面查询执行用户的订单:

    public static void findOrderByCustomer(Integer id){

            Session session = HibernateUtil.getSession();

            Customer customer = (Customer) session.get(Customer.class, id);

            Set<Order> orders = customer.getOrders();

            for(Order order : orders){

                System.out.println( "id:"+ order.getId()+

                                    ", orderNo:"+order.getOrderNo()+

                                    ", total:" + order.getTotal()+

                                    ", date:"+order.getDate().toLocaleString());

            }

        }

    一般使用的技术是双向的1-N级联,也就是在两个里面都配置级联关系,形成双向的级联。

    YangTengfei

    2013.11.28

  • 相关阅读:
    从苹果系统InstallESD.dmg里提取IOS
    Swift编程语言中文版教程---《The Swift Programming Language》
    VMware workstation 10.0的永久key
    VMware Workstation与Hyper-V不兼容。请先从系统中移除Hyper-V角色,然后再运行VMware Workstation。
    Unity3D游戏制作入门教程
    MyEclipse中文网
    机器学习中的两个概率模型
    机器学习中的两个概率模型
    EM算法概念
    EM算法概念
  • 原文地址:https://www.cnblogs.com/hbhzsysutengfei/p/3473208.html
Copyright © 2011-2022 走看看