Hibernate配置/使用小结

一、Hibernate介绍     

      之前使用过iBatis,虽然现在互联网行业使用Hibernate较少,但最近还是抽时间把Hibernate看了一下,出于对性能的考虑,Hibernate相比较而言最大的缺点就是性能的问题。其实这也是必然会出现的问题,任何框架对底层的包装都会产生这些性能问题,这个主要看我们对性能的要求到底到什么程度了。

      关于DAO模式:业务层屏蔽了数据访问的底层(Data Accessor)实现,业务层(Domain Object)仅包含与本领域相关的逻辑对象和算法。

      关于持久化:狭义的理解:Java对象存在于内存中,Hibernate将java对象持久化到关系型数据库中。广义的理解:保存,更新,删除,查询等操作都是持久化。确切的说,数据库中存放的是关系数据,而不是对象。我们说的”从数据库中加载对象“等说法,主要是站在hibernate客户端程序的角度来看待数据库访问操作的。客户程序可以假想数据库中存放的就是对象,只需要委托hibernate从数据库中去加载就行了,hibernate要做的就是把这些对象映射为数据库中的相应关系数据,大致流程如下:

      1.运用java反射机制(Constuctor.newInstance()),获取到对象的class类型(要求持久化类必须要有一个无参的构造函数);

      2.参考对象-关系映射,获取对象对应的数据表以及属性、字段的对应;
      3.生成SQL语句并执行(hibernate query内置了HQL语言,语法和SQL相似,不过它是面向对象的);

 

二、Hibernate使用  

  0. 表结构如下:

sample.minfo (Table)
=====================
id: INT
mname: VARCHAR
mage: INT
mgender: VARCHAR

      1.Hibernate的全局配置文件 hibernate.cfg.xml(两种配置形式,也可以配置成.properties)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <!-- SessionFactory -->
    <session-factory>
        <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3309/sample</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>
        <property name="hibernate.show_sql">false</property>
    </session-factory>
    
</hibernate-configuration>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://127.0.0.1:3309/sample
hibernate.connection.username=root
hibernate.connection.password=root
hibernate.show_sql=true

     当通过Configuration的默认构造函数来创建实例的时候,hibernate会到classpath下查找默认的hibernate.properties文件,如果找到,就把它的配置信息加载到内存中,默认情况下hibernate不会加载hibernate.cfg.xml文件,必须通过Configuration的configure()方法来显示加载:

     Configuration config = new Configuration().configure();

     hibernate.show_sql=true //表示在控制台打印hibernate生成的sql语句

     hibernate.dialect=org.hibernate.dialect.MySQLDialect //标示hibernate使用的SQL方言,这里是mySQL

     2. hibernate持久化类 monkey.java

package HibernateTest;

import java.util.StringTokenizer;

public class Monkey {

    private int id;

    private String firstName;

    private String lastName;

    // private String monkeyName;

    private int monkeyAge;

    private String monkeyGender;
    
    private String anotherGender;

    public String getAnotherGender() {
        return anotherGender;
    }

    public void setAnotherGender(String anotherGender) {
        this.anotherGender = anotherGender;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getMonkeyName() {
        // return monkeyName;
        return firstName + " " + lastName;
    }

    public void setMonkeyName(String monkeyName) {
        // this.monkeyName = monkeyName;
        StringTokenizer st = new StringTokenizer(monkeyName);
        firstName = st.nextToken();
        lastName = st.nextToken();
    }

    public int getMonkeyAge() {
        return monkeyAge;
    }

    public void setMonkeyAge(int monkeyAge) {
        this.monkeyAge = monkeyAge;
    }

    public String getMonkeyGender() {
        return monkeyGender;
    }

    public void setMonkeyGender(String monkeyGender) {
        this.monkeyGender = monkeyGender;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Monkey() {

    }

}

     3. 关系-对象配置文件 Monkey.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC   "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="org.hibernate.auction">
 <class name="HibernateTest.Monkey" table="minfo" lazy="false">
    <id name="id" column="id" type="int" >
      <generator class="increment"/>
    </id>
    <property name="monkeyName" column="mname" type="string" not-null="true" />
    <property name="monkeyAge" column="mage" type="int" not-null="true" />
    <property name="monkeyGender" column="mgender" type="string" not-null="true" />
    <property name="anotherGender" formula=" (select mgender from minfo) " />
  </class>
 </hibernate-mapping>

    4.测试程序

package HibernateTest;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class HibernateService {

    public static SessionFactory sessionFactory;

    // 初始化Hibernate,创建SessionFactory实例
    static {
        try {
            // 根据默认位置的Hibernate配置文件的配置信息,创建一个Configuration实例
            Configuration config = new Configuration();
            // 加载Monkey类的对象-关系映射文件
            config.addClass(Monkey.class);
            // 创建SessionFactory实例
            sessionFactory = config.buildSessionFactory();
        } catch (RuntimeException e) {
            e.printStackTrace();
            throw e;
        }
    }

    // 查询所有的Monkey对象,然后打印Monkey对象信息
    public void findAllMonkeys() {
        Session session = sessionFactory.openSession();// 创建一个会话
        Transaction tx = null;
        try {
            tx = session.beginTransaction();// 开始一个事物
            Query query = session
                    .createQuery(" from Monkey as m order by m.monkeyName asc");
            @SuppressWarnings("unchecked")
            List<Monkey> monkeys = query.list();
            Iterator<Monkey> it = monkeys.iterator();
            while (it.hasNext()) {
                Monkey monkey = it.next();
                System.out.println(monkey.getId() + "-"
                        + monkey.getMonkeyName() + "-" + monkey.getMonkeyAge()
                        + "-" + monkey.getMonkeyGender()+"-"+monkey.getAnotherGender());
            }
            tx.commit();
        } catch (RuntimeException e) {
            if (tx != null)
                tx.rollback();
            e.printStackTrace();
            throw e;
        } finally {
            session.close();
        }
    }

    public void saveMonkey(Monkey monkey) {
        Session session = sessionFactory.openSession();// 创建一个会话
        Transaction tx = null;
        try {
            tx = session.beginTransaction();// 开始一个事物
            session.save(monkey);
            tx.commit();
        } catch (RuntimeException e) {
            if (tx != null)
                tx.rollback();
            e.printStackTrace();
            throw e;
        } finally {
            session.close();
        }
    }

    public void deleteMonkey(Monkey monkey) {
        Session session = sessionFactory.openSession();// 创建一个会话
        Transaction tx = null;
        try {
            tx = session.beginTransaction();// 开始一个事物
            monkey = (Monkey) session.get(Monkey.class, monkey.getId());
            session.delete(monkey);
            tx.commit();
        } catch (RuntimeException e) {
            if (tx != null)
                tx.rollback();
            e.printStackTrace();
            throw e;
        } finally {
            session.close();
        }
    }
    
    public void updateMonkey(Monkey monkey,int age) {
        Session session = sessionFactory.openSession();// 创建一个会话
        Transaction tx = null;
        try {
            tx = session.beginTransaction();// 开始一个事物
            monkey = (Monkey) session.get(Monkey.class, monkey.getId());
            monkey.setMonkeyAge(age);
            session.update(monkey);
            tx.commit();
        } catch (RuntimeException e) {
            if (tx != null)
                tx.rollback();
            e.printStackTrace();
            throw e;
        } finally {
            session.close();
        }
    }

    public static void main(String[] args) {
        HibernateService service = new HibernateService();
        Monkey monkey = new Monkey();
        //monkey.setId(2);
        //monkey.setMonkeyName("libin");
        monkey.setFirstName("lee");
        monkey.setLastName("nicholas");
        monkey.setMonkeyAge(520);
        monkey.setMonkeyGender("M");
        //service.saveMonkey(monkey);
        //service.deleteMonkey(monkey);
        //service.updateMonkey(monkey, 1314);
        service.findAllMonkeys();
    }

}

     有几点需要说明的地方:

     A. 我们可以配置

<property name="monkeyGender" column="mgender" access="field" type="string" not-null="true" />

     access="field" 代表用hibernate使用反射机制直接访问持久化类的属性,而不是通过 getXXX 或 setXXX 方法

     B. 如果持久化类中没有设置monkeyName属性也没关系,hibernate默认会直接访问setName 和 getName 方法,

   例如上例我们就注释掉了// private String monkeyName; 因为我们有时候需要在这两个方法里写一下我们自己的逻辑,例如:

private String firstName;
private String lastName;
public String getMonkeyName() {
        // return monkeyName;
        return firstName + " " + lastName;
    }

public void setMonkeyName(String monkeyName) {
        // this.monkeyName = monkeyName;
        StringTokenizer st = new StringTokenizer(monkeyName);
        firstName = st.nextToken();
        lastName = st.nextToken();
    }

      有时候数据表里字段没有对应的firstName和lastName,我们需要组合一下然后属性配置还是配置monkeyName:

 <property name="monkeyName" column="mname" type="string" not-null="true" />

      因为如果持久化类中没有设置monkeyName属性也没关系,hibernate默认会直接访问setXXX 和 getXXX 方法;有时候我们可能需要加一些数据验证,外部输入调用持久化类的set方法时候验证数据合法性,但hibernate从数据库的读取一般都是合法的数据这个时候没必要验证,可以写成 access="field" 就解决了这个矛盾。

     hibernate可以访问各种级别的getXXX setXXX 包括private,如果某个属性我们只希望hibernate去set就可以把这个属性设置为private;

      C. formula 计算派生属性的值

      有时候持久化类的属性需要通过计算才能得出,这种属性称为派生属性,我们可以如下配置:

  private String anotherGender;

    public String getAnotherGender() {
        return anotherGender;
    }

    public void setAnotherGender(String anotherGender) {
        this.anotherGender = anotherGender;
    }

      数据库表中并没有anotherGender属性,但我们可以在配置文件中直接配置得到:

 <property name="anotherGender" formula=" (select mgender from minfo) " />

     然后通过查询得出:

@SuppressWarnings("unchecked")
            List<Monkey> monkeys = query.list();
            Iterator<Monkey> it = monkeys.iterator();
            while (it.hasNext()) {
                Monkey monkey = it.next();
                System.out.println(monkey.getId() + "-"
                        + monkey.getMonkeyName() + "-" + monkey.getMonkeyAge()
                        + "-" + monkey.getMonkeyGender()+"-"+monkey.getAnotherGender());
            }
            tx.commit();

     总结:Hibernate在初始化阶段,就会根据映射文件的映射信息为所有的持久化类预定义insert into table(a,b,c) values(?,?,?)/update/delete等语句;

     ?代表JDBC PreparedStatement中的参数,这些SQL语句都存放在SessionFactory缓存中,当执行Session的sava,delete,update等方法时,将从缓存中找到预定义的SQL语句,再把具体的参数绑定到该语句中执行,默认情况下,预定义的SQL语句包含了表的所有字段,不过我们可以控制:

<property name="monkeyName" update="false" column="mname" type="string" not-null="true" />

     monkeyName映射了持久化类的属性,也对应表中的mname字段,update="false",代表我们在更新这条记录的时候不回去更新这个字段(默认更新所有字段);

      一般情况下我们为了节省SQL的执行开销,会把dynamic-insert和dynamic-update都设置成true,这样SQL执行就只包含需要插入或更新的字段了;

      SessionFactory代表一个数据库存储源,如果只有一个数据库存储源那么只需要创建一个SessionFactory实例,创建一个SessionFactory实例需要消耗很多资源,它是一个重量级的对象,通过创建一个SessionFactory获得session是一个轻量级的对象,每个session实例和一个事务绑定。

      三、Hibernate的一些高级使用

转载于:https://www.cnblogs.com/NicholasLee/archive/2012/07/20/2601104.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值