Hibernate 初体验

Posted 陈东

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate 初体验相关的知识,希望对你有一定的参考价值。

为什么会产生 Hibernate Mybatis 这类的dao层框架

传统的jdbc 虽然执行速度很快,但是开发效率很低,随着面向对象开发的设计思想,在面向对象编程中 将对象 进行持久化,存入关系型的数据库时,由于关系型数据库的设计思想是数学思维,在持久化时,必须要对象拆分各个属性值,才可存入数据库;传统的jdbc 持久化时 对象持久化时 ,取出对象的一个一个属性,过去繁琐,并且不便于维护,而市场上的面向对象的数据库还并不成熟,所以为了调节面向对象设计的开发思想与落后的关系型数据库之间持久化时繁琐的问题,产生了一种新的设计规范

ORM (Object Relation Mapping) 

对象关系映射,是一种规范,调节目前面向对象的程序设计与主流的关系型数据库之间 发展不同步的问题,
关系 到对象的映射;
让编程时 可以全身心的用面向对象的设计思想去编程,用对象映射关系数据表,在持久化时,可以直接操作对象进行持久化。
优点:
开发效率高;
可维护性高;
缺点:
高效率的开发 对应也要失去性能,处理复杂关系时,性能会变差;
实现这种规范的框架之一
Hibernate
介绍:免费的开源java包,对象到关系之间的转变很容易,程序开发时可以完全的以面向对象的设计思想去开发。轻量级框架,低侵入,开发者活跃,开发文档也很全,
支持多种数据库,并且为了更好的操作各种数据库,它专门为每种数据库都准备了一套“方言”组件
可以这样理解:天津人对外讲普通话,但是对家乡人会用天津话去沟通,这样沟通更加容易,
它很有特点的一功能就是在配置完实体对象和表结构的映射文件之后,可以自动为你去创建表,
而且通过主配置文件 配置过数据库连接 事务,等操作之后,获取到的session 可以直接对“对象”持久化,不需要你去考虑sql语句,
但是由于它的这种方式,在处理复杂的sql语句持久化时,就显示出不足了,不够灵活;
 
环境搭建:
第一步:导入jar包
 
第二步:创建实体类
package hibernateDemo;

import java.util.Date;

/**
 * 持久化的bean类
 * 注意:
 * 1: id唯一标识 建议 使用封装类型
 * 2:这个类不能final修饰
 * 3:需要给这个类提供一个无参数的构造器,
 * 4:给所有的属性提供get set方法;
 * 5: 如果有设计集合数据的操作,集合类型 要使用接口类型 list 不允许实现类的类型 arrylist;
 * 创建对象的时候 是用 new 构造器方法 
 * @author Administrator
 *
 */
public class Person {
    public Person(){
        
    }
    private Integer id;
    private String name;
    private int passWord;
    private Date birthday;
    
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getPassWord() {
        return passWord;
    }
    public void setPassWord(int passWord) {
        this.passWord = passWord;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", passWord=" + passWord + ", birthday=" + birthday + "]";
    }
}

第三部:创建相应的映射文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping SYSTEM "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<!-- 映射文件 java对象Dao关系数据库的映射配置文件 -->
<hibernate-mapping  package = "hibernateDemo">
  <!-- class配置  类 对应表的映射
      对应的实体类就是 package+class的name
      table 表示关系数据库的表名 
   -->
    <class name="Person" table="t_person">
        <!-- id 指定 实体类中哪一个属性为 唯一标识ID -->
        <id name="id" >
            <!-- 自动生成id策略 -->
            <generator class="native"/>
        </id>
    <!-- 实体类的其他属性配置
        name:对应实体类的属性 column:对应表的字段名(若不指定 将默认使用类的属性名)
        
     -->
    <property name="name" column="t_name"/>
    <property name="passWord" column="t_passWord"/>
    <property name="birthday"/>
    
    </class>
</hibernate-mapping>

第四步 主配置文件 放在src目录下 官方的api上会默认去src下查hibernate.cfg.xml这个文件 还有其他方式下面介绍

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <!-- 显示执行的SQL语句 -->
        <property name="show_sql">true</property>
            <!-- 驱动 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <!-- 数据库url-->
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/medicine?useUnicode=true&amp;characterEncoding=utf-8</property>
        <!-- 访问数据库用户名 -->
        <property name="hibernate.connection.username">root</property>
        <!-- 访问数据库密码 -->
        <property name="hibernate.connection.password">root</property>
        <!--  如果使用的mysql数据版本在5.5之后的话,方言通常建议使用MySQL5InnoDBDialect
            MySQLDialect 不支持事务
            MySQLInnoDBDialect 支持事务
            为了更好的操作各种数据库,所以为每个数据库 准备了不同的方言 
         -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <!-- 自动创建表结构配置
            create-drop 在程序启动的时候创建对应数据库表结构,当SessionFatory关闭的时候会将创建的表结构删除
            create 在每次程序启动的时候先删除上次创建的数据库表结构,然后再创建对应新数据库表结构。
            update 在每次启动的时候会追加修改的表结构,但是不会影响原来的数据 (通常用这个)
            validate 在每次启动的时候会验证并修改的表结构。
         -->
        <property name="hibernate.hbm2ddl.auto">update</property>
        
        <!-- 告诉映射文件的位置  引入需要对应的配置文件-->
        <mapping resource="hibernateDemo/Person.hbm.xml"/>
        
    </session-factory>
</hibernate-configuration>

最后一步测试代码了

package test;

import java.util.Date;

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

import hibernateDemo.Person;

public class test {
    public static void main(String[] args) {
//加载 主配置文件的方式 还有一种读取properties文件的方式
//创建Configuration读取配置文件的 对象 可传参数,并加载配置文件hibernate.cfg.xml Configuration conf = new Configuration().configure(); //通过配置文件中的配置信息 获取数据库连接 //这种写法是hibernate4之前的写法 //sessionFactory是与应用程序生命周期一致的,多线程共享的 SessionFactory factory = conf.buildSessionFactory(); //相当于一次数据库的交互 代表一次操作 只为一次线程使用 线程结束 声明 over Session session = factory.openSession(); /** * 增删改 是需要 事务 */ Transaction tx = session.beginTransaction(); Person entity = new Person(); entity.setName("tom"); entity.setPassWord(123456); entity.setBirthday(new Date()); //面向对象的方式 持久化 session.persist(entity); /** * 提交事务 */ tx.commit(); session.close(); } }

数据库的显示

 查询 get方法 立即执行
    /**
     * get方式返回的是一个持久化类的实例 一执行就立即查询 执行查询语句立即查询
     * 
     */
    
    public static void get(){
        Configuration conf = new Configuration().configure();
        /**
         * 推荐使用的获取factory 高效安全
         */
        ServiceRegistry sb =  new ServiceRegistryBuilder().applySettings(conf.getProperties()).buildServiceRegistry();
        SessionFactory factory = conf.buildSessionFactory(sb);
        Session session = factory.openSession();
        //根据id查询数据
        Person o = (Person)session.get(Person.class, 2);
        System.out.println(o);
        session.close();
        factory.close();
        
    }

查询 2 load延迟查询

    /**
     * load 返回的是一个持久化类的代理,当正真访问除了id以外的属性时,才去发起sql查询;
     * 延迟查询 ,第一次查询只不过是给你一个代理 不是真的查询。真正的查询是你在调用这个实例的某一个属性才会具体查询; 
     * 当给定的id不存在时,什么时候调用什么时候抛出错误异常;不调用不会报错;
     * 可通过 映射文件上的class标签内的 lazy="false" 改成立即执行
     */
    public static void load(){
        Configuration conf = new Configuration().configure();
        /**
         * 推荐使用的获取factory 高效安全
         */
        ServiceRegistry sb =  new ServiceRegistryBuilder().applySettings(conf.getProperties()).buildServiceRegistry();
        SessionFactory factory = conf.buildSessionFactory(sb);
        Session session = factory.openSession();
        //根据id查询数据
        Person o = (Person)session.load(Person.class, 10);
    System.out.println(o);
        session.close();
        factory.close();
    }

更新 引进session的持久化对象概念


 当获取到 session管理的对象时(get load merge 等等获取到的对象),你可以完全不用update 或merge 方法 去再次修改
 对于session管理的对象,在session的连接断开的时候,会自动同步被管理的对象与数据库中的数据,若相同则不改变,若不相同,会以管理的对象为主更新数据库中的数据;

/**
     * 修改通过get方法获得持久化对象
     * 更新了全部字段 更改的加上未更改的全部更新了仪表
     * 真正的执行sql语句是在session关闭的时候
     */
    public static void update1(){
        Configuration conf = new Configuration().configure();
        /**
         * 推荐使用的获取factory 高效安全
         */
        ServiceRegistry sb =  new ServiceRegistryBuilder().applySettings(conf.getProperties()).buildServiceRegistry();
        SessionFactory factory = conf.buildSessionFactory(sb);
        Session session = factory.openSession();
        Transaction tx = session.beginTransaction();
        Person o = (Person) session.get(Person.class, 1);
        System.out.println(o.getName());
        o.setName("Json");
        session.update(o);
        tx.commit();
        session.close();
        factory.close();
        
    }
    /**
     * 修改通过自己创建的的对象
     * 更新了全部字段 更改的加上未更改的全部更新了表
     * 若只设置一个属性值 其他值全部被覆盖为空 
     * 真正的执行sql语句是在session关闭的时候
     * 1:id必须有 ,并且必须对应数据库里某一条记录。
     */
    public static void update2(){
        Configuration conf = new Configuration().configure();
        /**
         * 推荐使用的获取factory 高效安全
         */
        ServiceRegistry sb =  new ServiceRegistryBuilder().applySettings(conf.getProperties()).buildServiceRegistry();
        SessionFactory factory = conf.buildSessionFactory(sb);
        Session session = factory.openSession();
        Transaction tx = session.beginTransaction();
        Person o = new Person();
        o.setId(2);
        o.setName("高效");
        session.merge(o);
        tx.commit();
        session.close();
        factory.close();
    
    }
    /**
     * 
     * 引进持久化状态
     * 当获取到 session管理的对象时(get load merge 等等获取到的对象),你可以完全不用update 或merge 方法 去再次修改
     * 对于session管理的对象,在session的连接断开的时候,会自动把被管理的对象去数据库比对,若相同则不改变,若不相同,会以管理的对象为主更新数据库中的数据;
     */
    public static void merge(){
        Configuration conf = new Configuration().configure();
        /**
         * 推荐使用的获取factory 高效安全
         */
        ServiceRegistry sb =  new ServiceRegistryBuilder().applySettings(conf.getProperties()).buildServiceRegistry();
        SessionFactory factory = conf.buildSessionFactory(sb);
        Session session = factory.openSession();
        Transaction tx = session.beginTransaction();
        Person o = new Person();
        o.setId(2);
        o.setName("高效2");
        Person p =  (Person) session.merge(o);
        System.out.println("修改后o"+o);
        System.out.println("修改后p"+p);
        o.setName("高效33");
        p.setName("高效pp");
        System.out.println("再次修改后o"+o);
        System.out.println("再次修改后p"+p);
        tx.commit();
        session.close();
        factory.close();
    
    }

 

 
 
 

以上是关于Hibernate 初体验的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate 初体验

SSH初体验系列--Hibetnate--2--crud操作

vs code初体验

SSH初体验系列--Hibernate--3--单值与分页查询

轻量级DAO层实践初体验

Hibetnate+postgresql 初体验及demo