Hibernate学习笔记

转自【SSH进阶之路】Hibernate基本原理(一)

 

Hibernate就是对数据库进行封装,使得程序员可以直接操作对象而不用写具体的数据库操作。

ORM(Object Relation Mapping,对象关系映射)的作用是在关系型数据库和对象之间做了一个映射。从对象(Object)映射到关系(Relation),再从关系映射到对象。这样,我们在操作数据库的时候,不需要再去和复杂SQL打交道,只要像操作对象一样操作它就可以了(把关系数据库的字段在内存中映射成对象的属性)。

Hibernate是一个开放源代码的ORM框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的ORM框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。

Hibernate的核心:

 

     从上图中,我们可以看出Hibernate六大核心接口,两个主要配置文件,以及他们直接的关系。Hibernate的所有内容都在这了。那我们从上到下简单的认识一下,每个接口进行一句话总结。

1、Configuration接口:负责配置并启动Hibernate

2、SessionFactory接口:负责初始化Hibernate

3、Session接口:负责持久化对象的CRUD操作

4、Transaction接口:负责事务

5、Query接口和Criteria接口:负责执行各种数据库查询

注意:Configuration实例是一个启动期间的对象,一旦SessionFactory创建完成它就被丢弃了。

 

Hibernate初探之单表映射

首先建一个hibernate.cfg.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!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>
        <!-- 配置数据库驱动 -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <!-- 连接数据库名称  设置字符格式防止中文乱码  -->
        <property name="connection.url">jdbc:mysql://localhost:3306/hibernate?useUnicode=true&amp;characterEncoding=UTF-8</property>
        <!-- /// 表示本地数据库  下面语句同上面一条  -->
         <property name="connection.url">jdbc:mysql:///hibernate?useUnicode=true&amp;characterEncoding=UTF-8</property>
        <!-- 用户名 -->
        <property name="connection.username">root</property>
        <!-- 密码 -->
        <property name="connection.password">123456</property>
        <!-- 指定对应数据库的方言,hibernate为了更好适配各种关系数据库,针对每种数据库都指定了一个方言dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        
        <!-- sql语句输出到控制台 -->
        <property name="show_sql">true</property>
        <!-- 输出到控制台的sql语句进行排版 -->
        <property name="format_sql">true</property>
        <!-- create:删除以前的创建新的  update:原有的基础上更新   -->
        <property name="hbm2ddl.auto">create</property>
        <!-- 映射文件 -->
        <mapping resource="Students.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

写一个学生类  

实体类和数据库中的表相对应

import java.util.Date;

public class Students {
    
    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;
    }

    @Override
    public String toString() {
        return "Students [sid=" + sid + ", sname=" + sname + ", gender=" + gender + ", birthday=" + birthday
                + ", address=" + address + "]";
    }
    
}
Students.java

创建对象-关系映射配置文件,后缀是.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 2017-1-29 20:54:05 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <!-- 映射的类和表 -->
    <class name="Students" table="STUDENTS">
    <!-- 被id标签括起来表示主键 name类中名称  type数据类型:Java的数据类型或者Hibernate的数据类型  -->
        <id name="sid" type="int">
            <column name="SID" />
            <!-- 主键生成策略  native根据底层数据库自动生成,例如MySQL就是auto_increment  assigned手工赋值 -->
            <generator class="native" />
        </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>
    </class>
</hibernate-mapping>

 

使用 junit 测试:

@Test 测试注释标签  测试方法

@Before 初始化方法  执行测试方法之前会执行这个方法

@After 释放资源     执行测试方法之后会执行这个方法

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

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();
        // session = sessionFactory.getCurrentSession();
        // 开启事务
        transaction = session.beginTransaction();
    }
    @After
    public void destroy() {
        transaction.commit();    // 提交事务
        session.close();        // 关闭会话
        sessionFactory.close();    // 关闭会话工厂
    }
    @Test
    public void testSaveStudents() {
        Students s = new Students(1, "段文弱", "男", new Date(), "天朝");
        session.save(s);
    }
}

 

Hibernate执行流程

session是一个操纵数据库对象,session与connection是多对一的关系。

session默认事务不是自动提交。需要Transaction提交。transaction.commit();

可以通过设置doWork()变成自动提交(不推荐)

session.doWork(new Work(){
    @Override
    public void execute(Connection connection) throws SQLException {
        connection.setAutoCommit(true);
    }
});

 

获得session:

1.openSession       每次都获得一个新的session,需要手动关闭

2.getCurrentSession  使用现有的session对象,需要在hibernate.cfg.xml中配置

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

在事务提交或者回滚之后会自动关闭,(所以啊……不需要关闭……会有错误!错了好多次才反应过来!

 

基本数据类型:

时间类型:

对象类型

1.clob和text对应大文本文件,blob对应大的二进制文件,例如视频音频图片

2.java中的clob对应存储大文本文件,java中的blob对应存储大二进制文件

MySQL不支持标准SQL的CLOB类型,在Mysql中,用TEXT,MEDIUMTEXT及LONGTEXT类型来表示长度超过255的长文本数据

@Test
public void testWriteBlob() throws IOException {
    Students s = new Students(100, "段文弱", "男", new Date(), "天朝");
    File file = new File("E:"+File.separator+"图片"+File.separator+"bobo.jpg");
    // 获得照片文件的输入流
    InputStream input = new FileInputStream(file);
    // 创建一个Blob对象
    Blob image = Hibernate.getLobCreator(session).createBlob(input, input.available());
    // 设置照片属性
    s.setPicture(image);
    session.save(s);
}

@Test
public void testReadBlob() throws Exception {
    Students s = (Students)session.get(Students.class, 1);
    Blob image = s.getPicture();
    InputStream input = image.getBinaryStream();
    File file = new File("E:"+File.separator+"bobo.jpg");
    OutputStream output = new FileOutputStream(file);
    // 创建缓冲区
    byte[] buffer = new byte[input.available()];
    //System.out.println(input.available());
    input.read(buffer);
    output.write(buffer);
    input.close();
    output.close();
}

组件属性:某个属性是用户自定义的对象

<component name="取的名字" class="类名">
        <property name="类中属性" column="对应生成数据库中列属性名">
</component>

会在数据库中将自定义类中的属性也当做一个字段。

增删改查:

Students s = new Students();

//增加数据
session.save(s);

// 获取  Object get/load(Class, 主键)
Students s = (Students)session.get(Students.class, 1);
Students s = (Students)session.load(Students.class, 1);

// 修改
session.update(s);

// 删除
session.delete(s);

get load区别:

1.get调用后立即发出sql语句,并返回对象。load调用后返回代理对象,保存了实体对象id,直到使用了对象的非主键属性时才发出sql语句

2.当查询到数据为空时,get返回null,load返回objectNotFound异常

posted @ 2017-02-02 17:31  我不吃饼干呀  阅读(372)  评论(0编辑  收藏  举报