Hibernate学习笔记(一)

第一章 Hibernate初识

1.什么是ORM?

ORM(Object/Relationship Mapping):对象关系映射
利用面向对象思想编写的数据库应用程序最终都是把对象信息保存在关系型数据库中,于是要编写很多和底层数据库相关的SQL语句。这与面向对象的思想格格不入。所以需要一种ORM框架技术,使其真正的面向对象。Hibernate就是这样一种框架。
SQL语句的不好之处
1. 在不同的数据库使用的SQL语法不同,比如:PL/SQL与T/SQL
2. 同样的功能在不同的数据库中有不同的实现方式。比如分页SQL技术
3. 程序过分依赖SQL对程序的移植及拓展,维护等带来很大的麻烦。

2.Hibernate简介

2.1 什么是Hibernate?

Hibernate是java领域的一款开源的ORM框架技术。
Hibernate对JDBC进行了非常轻量级的对象封装。
这里写图片描述

2.2 其他主流ORM框架技术

  1. MyBatis:前身就是著名的iBatis
  2. Toplink:后被Oracle收购,并重新包装为Oracle AS TopLink
  3. EJB:本身就是JAVAEE的规范

3.编写第一个Hibernate

3.1 开发工具:

Eclipse,MySQL
Hibernate Tools for Eclipse Plugins

Hibernate Tools是由JBoss推出的一个Eclipse综合开发工具插件,该插件可以简化ORM框架Hibernate,以及JBoss Seam,EJB3等的开发工作。

3.2 步骤

  1. 创建Hibernate的配置文件
  2. 创建持久化类
  3. 创建对象-关系映射文件
  4. 通过Hibernate API编写访问数据库的代码

需要导入的jar包
导入Hibernate必须的jar包
hibernate-release-4.2.4.Final\lib\required
导入Mysql的jdbc驱动
导入Junit4的jar包

3.2 完整案例

Hibernate配置文档hibernate.cfg.xml

<?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>
    <session-factory>
        <!-- 基本配置 -->
        <property name="connection.username">root</property>
        <property name="connection.password">123</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql:///hibernate?useUnicode=true&amp;characterEncoding=UTF-8</property>
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- 常用配置 -->
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <property name="hbm2ddl.auto">create</property>

        <mapping resource="Students.hbm.xml"/>

        <!-- 开始一个hibernate项目的步骤
        1.在eclipse上安装Hibernate Tools for Eclipse Plugins
            下载地址:https://sourceforge.net/projects/jboss/files/JBossTools/JBossTools4.1.x/
            安装:Help->install new software->add->archive->找到下载的安装包
        2.导入Hibernate(hibernate-release-4.2.4.Final\lib\required)、junit4、mysql-jdbc三个jar包
            Hibernate下载地址:http://hibernate.org/orm/downloads/
            A:window->preferences->java->build path->user libraries->new->
            add extential jars完成用户libraries的创建(新建三个用户类库)
            然后把已经准备好的各个jar包分别add进去(D:/APP/lib),这样可以方便后面每次导入常用jar包
            B:选中项目->build path->add libraries->user libraries->选中刚建的libraries完成即可
        3.创建和配置Hibernate配置文档(hibernate.cfg.xml)
            A:创建  选中项目下的src->new->other->hibernate->hibernate configuration file->next完成即可
            B:配置  上面八条代码(hbm2ddl.auto的create表示先删除表,在创建表,再插入数据)
        4.创建一个持久化类,该类满足javabean的设计原则
        5.创建对象-关系映射文件(Students.hbm.xml)
            A:创建  选中项目下的src->new->other->hibernate->hibernate xml mapping file->next完成
            B:在配置文件中配置<mapping resource="Students.hbm.xml"/>
        6.创建数据库(hibernate)
        7.junit测试
            A:在项目跟目录下创建test文件夹(source folder),一般测试用例都放在这个文件夹
            B:创建测试类,理解test、after、before三个注解执行顺序
        8.访问数据库,见学生测试类
        9.运行测试类,成功自动建表和插入数据!(表是自动生成的哦)
         -->
    </session-factory>
</hibernate-configuration>

持久化类Students.java

import java.util.Date;

//学生类(持久化类,满足javabean的设计原则)
public class Students {
    // 1.公有的类
    // 2.提供公有的不带参数的默认构造方法
    // 3.属性私有
    // 4.属性必须封装

    private int sid;
    private String sname;
    private String gender;
    private Date birthday;
    private String address;

    public Students() {

    }
    public Students(int sid, String sname, String gender, Date birthday,
            String address) {
        // super();
        this.sid = sid;
        this.sname = sname;
        this.gender = gender;
        this.birthday = birthday;
        this.address = address;
    }
    public int getSid() {
        return sid;
    }
    public void setSid(int sid) {
        this.sid = sid;
    }
    public String getSname() {
        return sname;
    }
    public void setSname(String sname) {
        this.sname = sname;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    // 方便测试,重写tostring方法
    @Override
    public String toString() {
        return "Students [sid=" + sid + ", sname=" + sname + ", gender="
                + gender + ", birthday=" + birthday + ", address=" + address
                + "]";
    }
}

对象关系映射文件Students.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">
<!-- Generated 2016-7-5 16:50:39 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="Students" table="STUDENTS">
        <id name="sid" type="int">
            <column name="SID" />
            <generator class="assigned" />
        </id>
        <property name="sname" type="java.lang.String">
            <column name="SNAME" />
        </property>
        <property name="gender" type="java.lang.String">
            <column name="GENDER" />
        </property>
        <property name="birthday" type="java.sql.Date">
            <column name="BIRTHDAY" />
        </property>
        <property name="address" type="java.lang.String">
            <column name="ADDRESS" />
        </property>
    </class>
</hibernate-mapping>

测试类StudentsTest.java

//测试类
public class StudentsTest {
    private SessionFactory sessionFactory;
    private Session session;
    private Transaction transaction;

    @Before
    public void Init() {
        // 创建事物对象
        Configuration config = new Configuration().configure();
        // 创建服务器注册对象
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                .applySettings(config.getProperties()).buildServiceRegistry();
        //创建会话工厂对象
        sessionFactory = config.buildSessionFactory(serviceRegistry);
        //会话对象
        session = sessionFactory.openSession();
        //开启事务
        transaction = session.beginTransaction();
    }

    @After
    public void destory() {
        transaction.commit();//提交事务
        session.close();//关闭会话
        sessionFactory.close();//关闭会话工厂
    }

    @Test
    public void testSaveStudents() {
        //生成学生对象
        Students s = new Students(1, "张三丰", "男", new Date(), "武当山");
        session.save(s);//把对象保存进数据库
    }
}

这里写图片描述

第二章 Hibernate进阶

1. hibernate.cfg.xml常用配置

这里写图片描述

2. session简介

  1. 不建议直接使用jdbc的connection操作数据库,而是通过使用session操作数据库。
  2. session可以理解为操作数据库的对象
  3. session以connection,是多对一关系,每个session都有一个与之对应的connection,一个connection不同时刻可以供多个session使用
  4. 把对象保存在数据库中需要调用session的各种方法,如:save(),update(),delete(),createQuery()
    这里写图片描述

3. transaction简介

  • hibernate对数据库的操作都是封装在事务当中的,并且默认是非自动提交的方式。所以用session保存对象时,如果不开启事务,并且手工提交事务,对象并不会真正保存在数据库中。
  • 如果你想让hibernate象jdbc一样自动提交事务,必须调用session对象的doWork()方法,获得jdbc的connection后,设置其为自动提交事务模式。(通常并不推荐这么做
    这里写图片描述

4. session详解

4.1 如何获得session

  1. openSession
  2. getCurrentSession
    如果使用getCurrentSession方法获得事务,需要在hibernate.cfg.xml文件中进行配置:
    如果是本地事务(jdbc事务)

    <propertyname="hibernate.current_session_context_class">thread</property>

如果是全局事务(jta事务)

<propertyname="hibernate.current_session_context_class">jta</property>

4.2 opemSession与getCurrentSession的区别

public class SessionTest {
    // 以下两个测试方法用于测试两种获得session对象的区别
    @Test
    public void testOpenSession() {
        // 获得配置对象
        Configuration config = new Configuration().configure();
        // 获得服务器注册对象
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                .applySettings(config.getProperties()).buildServiceRegistry();
        // 获得sessionFactory对象
        SessionFactory sessionFactory = config
                .buildSessionFactory(serviceRegistry);
        // 获得session对象
        Session session1 = sessionFactory.openSession();
        Session session2 = sessionFactory.openSession();
        //证明openSession每次创建新的session对象
        System.out.println(session1 == session2);// false
        // if (session != null) {
        // System.out.println("session创建成功!");
        // } else {
        // System.out.println("session创建失败!");
        // }
    }

    @Test
    public void testGetCurrentSession() {
        // 获得配置对象
        Configuration config = new Configuration().configure();
        // 获得服务器注册对象
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                .applySettings(config.getProperties()).buildServiceRegistry();
        // 获得sessionFactory对象
        SessionFactory sessionFactory = config
                .buildSessionFactory(serviceRegistry);
        // 获得session对象
        // 必须在hibernate.cfg.xml中配置<property
        // name="hibernate.current_session_context_class">thread</property>
        //否则session创建失败
        Session session1 = sessionFactory.getCurrentSession();
        Session session2 = sessionFactory.getCurrentSession();
        //证明getCurrentSession()每次使用现有的session对象
        System.out.println(session1 == session2);// true
        // if (session != null) {
        // System.out.println("session创建成功!");
        // } else {
        // System.out.println("session创建失败!");
        // }
    }

    // 以下两个测试方法用于测试两种获得session对象的区别之
    //openSession在提交提交事务或者回滚后需要手动关闭会话,否则容易导致连接池溢出
    //而getCurrentSession提交后会自动关闭
    @Test
    public void testSaveStudentsWithOpenSession() {
        // 获得配置对象
        Configuration config = new Configuration().configure();
        // 获得服务器注册对象
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                .applySettings(config.getProperties()).buildServiceRegistry();
        // 获得sessionFactory对象
        SessionFactory sessionFactory = config
                .buildSessionFactory(serviceRegistry);
        // 创建session对象
        Session session1 = sessionFactory.openSession();
        // 开启事务
        Transaction transaction = session1.beginTransaction();
        // 生成一个学生对象
        Students s = new Students(1, "张三", "男", new Date(), "北京");
        //两次的打印的hashcode不同,说明两次用的不是同一个session。
        session1.doWork(new Work() {

            @Override
            public void execute(Connection connection) throws SQLException {
                System.out.println("connection hashCode:"
                        + connection.hashCode());
            }
        });

        session1.save(s);
        // session1.close();
        transaction.commit();// 提交事务

        Session session2 = sessionFactory.openSession();
        transaction = session2.beginTransaction();
        s = new Students(2, "李四", "男", new Date(), "上海");

        session2.doWork(new Work() {

            @Override
            public void execute(Connection connection) throws SQLException {
                System.out.println("connection hashCode:"
                        + connection.hashCode());
            }
        });

        session2.save(s);
        transaction.commit();
    }

    @Test
    public void testSaveStudentsWithGetCurrentSession() {
        // 获得配置对象
        Configuration config = new Configuration().configure();
        // 获得服务器注册对象
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                .applySettings(config.getProperties()).buildServiceRegistry();
        // 获得sessionFactory对象
        SessionFactory sessionFactory = config
                .buildSessionFactory(serviceRegistry);
        // 创建session对象
        Session session1 = sessionFactory.getCurrentSession();
        // 开启事务
        Transaction transaction = session1.beginTransaction();
        // 生成一个学生对象
        Students s = new Students(1, "张三", "男", new Date(), "北京");

        session1.doWork(new Work() {

            @Override
            public void execute(Connection connection) throws SQLException {
                System.out.println("connection hashCode:"
                        + connection.hashCode());
            }
        });

        session1.save(s);
        // session1.close();
        transaction.commit();// 提交事务

        Session session2 = sessionFactory.getCurrentSession();
        transaction = session2.beginTransaction();
        s = new Students(2, "李四", "男", new Date(), "上海");

        session2.doWork(new Work() {

            @Override
            public void execute(Connection connection) throws SQLException {
                System.out.println("connection hashCode:"
                        + connection.hashCode());
            }
        });

        session2.save(s);
        transaction.commit();
    }
}

5. 对象关系映射常用配置

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

第三章 Hibernate单表操作

1. 单一主键

  • assigned 由java应用程序负责生成(手工赋值)
  • native 由底层数据库自动生成标识符,如果是MySQL就是increment,如果是Oracle就是sequence,等等

2. 基本类型

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

3. 对象类型

这里写图片描述

4. 组件属性

这里写图片描述
Students .java

//学生类(持久化类,满足javabean的设计原则)
public class Students {
    // 1.公有的类
    // 2.提供公有的不带参数的默认构造方法
    // 3.属性私有
    // 4.属性必须封装

    private int sid;
    private String sname;
    private String gender;
    private Date birthday;
    // private String address;
    //对象类型
    private Blob picture;
    //组件属性
    private Address address;

    public Students() {
    }

    public Students(int sid, String sname, String gender, Date birthday,
            String address) {
        // super();
        this.sid = sid;
        this.sname = sname;
        this.gender = gender;
        this.birthday = birthday;
        //this.address = address;
    }
//、、、、、、

students.hbm.xml

<hibernate-mapping>
    <class name="Students" table="STUDENTS">
        <id name="sid" type="int">
            <column name="SID" />
            <generator class="assigned" />
        </id>
        <property name="sname" type="java.lang.String">
            <column name="SNAME" />
        </property>
        <property name="gender" type="java.lang.String">
            <column name="GENDER" />
        </property>
        <property name="birthday" type="java.util.Date">
            <column name="BIRTHDAY" />
        </property>
        <!-- 
        <property name="address" type="java.lang.String">
            <column name="ADDRESS" />
        </property>
         -->
         <!-- 对象类型 -->
        <property name="picture" type="java.sql.Blob">
            <column name="PICTURE" />
        </property>
        <!-- 组件属性 -->
        <component name="address" class="Address">
            <property name="postcode" column="POSTCODE"/>
            <property name="phone" column="PHONE"/>
            <property name="address" column="ADDRESS"/>
        </component>
    </class>
</hibernate-mapping>

StudentsTest.java

//测试类
public class StudentsTest {
    private SessionFactory sessionFactory;
    private Session session;
    private Transaction transaction;
    @Before
    public void Init() {
        // 创建事物对象
        Configuration config = new Configuration().configure();
        // 创建服务器注册对象
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                .applySettings(config.getProperties()).buildServiceRegistry();
        // 创建会话工厂对象
        sessionFactory = config.buildSessionFactory(serviceRegistry);
        // 会话对象
        session = sessionFactory.openSession();
        // 开启事务
        transaction = session.beginTransaction();
    }

    @After
    public void destory() {
        transaction.commit();// 提交事务
        session.close();// 关闭会话
        sessionFactory.close();// 关闭会话工厂
    }

    // 测试主键
    //测试组合属性
    //1.创建组合属性类(Address) 2.修改实体类(Students) 3.修改映射文件
    @Test
    public void testSaveStudents() {
        // 生成学生对象
        // Students s = new Students(1, "张三丰", "男", new Date(), "武当山");
        Students s = new Students();
        s.setSid(100);// 当<generator class="native" />时,这行代码不起作用
        s.setSname("张三丰");
        s.setGender("男");
        s.setBirthday(new Date());
        //s.setAddress("武当山");
        Address address = new Address("710068", "029888888", "武汉市");
        s.setAddress(address);//数据库address列变为三列了
        session.save(s);// 把对象保存进数据库
    }

    //测试Blob(向数据库存储照片)
    @Test
    public void testWriteBlob() throws Exception{
        Students s = new Students(2, "张三丰", "男", new Date(), "武当山");
        //先获取照片文件
        File f = new File("d:"+File.separator+"boy.jpg");
        //获得照片文件的输入流
        InputStream input = new FileInputStream(f);
        //创建一个Blob对象
        Blob image = Hibernate.getLobCreator(session).createBlob(input, input.available());
        //设置照片属性
        s.setPicture(image);
        //保存学生
        session.save(s);
    }

    //测试向数据库读取Blob数据(照片)
    @Test
    public void testReadBlob() throws Exception{
        Students s = (Students) session.get(Students.class,2);
        //获取Blob对象
        Blob image = s.getPicture();
        //获得照片的输入流
        InputStream input = image.getBinaryStream();
        //创建输出流
        File f = new File("d:"+File.separator+"dest.jpg");
        //获得输出流
        OutputStream output = new FileOutputStream(f);
        //创建缓冲区
        byte[] buff = new byte[input.available()];
        input.read(buff);
        output.write(buff);
        input.close();
        output.close();
    }
}

5. 单表操作CRUD实例

5.1 常用方法

  • save
  • update
  • delete
  • get/load(查询单个记录)

5.2 get与load方法的区别

  1. 在不考虑缓存的情况下,get方法会在调用之后立即向数据库发出sql语句,返回持久化对象。
  2. load方法会在调用之后返回一个代理对象。这个代理对象只保存了实体对象的id,直到使用对象的非主键属性时才会发出sql语句。
  3. 查询数据库中不存在的数据时,get方法返回null。load方法则抛出异常org.hibernate.ObjectNotFoundExcetion.
//测试类
public class StudentsTest {

    private SessionFactory sessionFactory;
    private Session session;
    private Transaction transaction;

    @Before
    public void Init() {
        // 创建事物对象
        Configuration config = new Configuration().configure();
        // 创建服务器注册对象
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                .applySettings(config.getProperties()).buildServiceRegistry();
        // 创建会话工厂对象
        sessionFactory = config.buildSessionFactory(serviceRegistry);
        // 会话对象
        session = sessionFactory.openSession();
        // 开启事务
        transaction = session.beginTransaction();

    }

    @After
    public void destory() {
        transaction.commit();// 提交事务
        session.close();// 关闭会话
        sessionFactory.close();// 关闭会话工厂
    }

    // 测试主键
    // 测试组合属性
    // 1.创建组合属性类(Address) 2.修改实体类(Students) 3.修改映射文件
    //也测试了session.save()方法
    @Test
    public void testSaveStudents() {
        // 生成学生对象
        // Students s = new Students(1, "张三丰", "男", new Date(), "武当山");
        Students s = new Students();
        s.setSid(100);// 当<generator class="native" />时,这行代码不起作用
        s.setSname("张三丰");
        s.setGender("男");
        s.setBirthday(new Date());
        // s.setAddress("武当山");
        Address address = new Address("710068", "029888888", "武汉市");
        s.setAddress(address);
        session.save(s);// 把对象保存进数据库
    }

    // 测试get查询方法
    @Test
    public void testGetStudents() {
        // 不管是否使用到s对象,查询语句会马上发出
        Students s = (Students) session.get(Students.class, 100);
        // 成功打印出s对象
        // System.out.println(s);

        // 反射技术,打印出类名,测试get方法返回的是持久化类的对象,而post方法返回的是代理对象
        System.out.println(s.getClass().getName());//Students
    }

    // 测试load查询方法
    @Test
    public void testLoadStudents() {
        // 如果没有用s对象,那么后台不会有任何的sql语句输出
        Students s = (Students) session.load(Students.class, 100);
        //这里打印输出s对象,使用到了s对象,发出了sql语句,与get方法效果一样
         //System.out.println(s);

        // 反射技术,打印出类名,测试get方法返回的是持久化类的对象,而post方法返回的是代理对象
        System.out.println(s.getClass().getName());//Students_$$_javassist_0
    }

    // 测试update查询方法
    @Test
    public void testUpdateStudents() {
        Students s = (Students) session.load(Students.class, 100);
        s.setGender("女");
        session.update(s);
    }

    // 测试delete删除方法
    @Test
    public void testDeleteStudents() {
        Students s = (Students) session.load(Students.class, 100);
        session.delete(s);
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值