第一天
一。Hibernate认识
ORM(Object/Relationship Mapping):对象/关系映射。
Hibernate就是一种开源的ORM框架技术。
Hibernate对JDBC进行了非常轻量级的封装。
Hibernate通常在业务逻辑层和数据库层中间是持久化层
二。开发前准备
开发工具:Eclipse
插件:Hibernate Tools for Eclipse Plugins -------------------------可以自动生成配置文档
Hibernate Tools是由JBoss推出的一个Eclipse综合开发工具插件,主要是简化Hibernate的开发。
安装Hibernate Tools插件
重启Eclipse后
File-->New-->Other-->Hibernate出现一下画面,证明装成功
新建工程
导入Hibernate必须的jar包
hibernate-release-4.2.4.Final\lib\required
导入mysql的jdbc驱动
mysql-connector-java-5.1.7-bin.jar
导入Junit4的jar包-------单元测试使用
junit-4.1.0.jar
1.新建一个普通的java项目
2.导入所需的jar包
把需要使用的jar包放入mylib目录下
打开Eclipse----->Window------>Preferences
添加三个用户自定义类库
在新建的工程中导入这些jar包
右键 项目名称hibernate_w_01----->Properties
三。Hibernate例子(版本使用HIBERNATE4.2.4+ MySQL6.0)
1.创建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">
-->
<!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>
<!-- 指定连接数据库的url -->
<property name="connection.url">jdbc:mysql:///hibernate?useUnicode=true&characterEncoding=UTF-8</property>
<!-- 指定数据库的方言 -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 指定连接数据库的用户名 -->
<property name="connection.username">root</property>
<!-- 指定连接数据库的密码 -->
<property name="connection.password">123456</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- 指定数据库生成策略 -->
<property name="hbm2ddl.auto">create</property>
<mapping resource="students.hbm.xml"/>
</session-factory>
</hibernate-configuration>
2.创建持久化类
在src目录下创建一个名为:Students.java的学生类
package hibernate_w_01;
import java.sql.Date;
//学生类
public class Students {
// javaBeans设计原则
// 1.共有的类
// 2.提供共有的不带参数的默认的构造方法
// 3.属性私有
// 4.属性setter/getter封装
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;
}
public String toString() {
return "Students [sid=" + sid + ", sname=" + sname + ", gender="
+ gender + ", birthday=" + birthday + ", address=" + address
+ "]";
}
}
3.创建对象-关系映射文件
在src下新建
在hibernate.cfg.xml文件中添加一段<mapping resourse="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">
-->
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-7-5 12:46:30 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>
使用Junit进行单元测试
新建一个源文件夹
选中项目hibernate_w_01--------New------>Source Folder
使用navicat连接MySQL建立一个新数据库
4.通过Hibernate API编写访问数据库的代码
在test目录下创建测试类:
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
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();
//开启事务
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);
}
}
运行结果:
第二天
1.hibernate.cfg.xml常用配置
属性名称 | 含义 |
hibernate.show_sql | 是否把hibernate运行时的SQL语句输出到控制台,编码阶段便于测试。 |
hibernate.format_sql | 输出到控制台的SQL语句是否进行排版,便于阅读。建议设置为true。 |
hbm2ddl.auto | 可以帮助由java代码生成数据库脚本,进而生成具体的表结构。create | update | create-drop | validate |
hibernate.default_schema | 默认的数据库(在数据库前边加前缀) |
hibernate.dialect | 配置Hibernate数据库方言,Hibernate可针对特殊的数据库进行优化 |
2.session简介
hibernate的执行流程
seeeion和JDBC中的connection作用雷同,可以把session理解为操作数据库的对象。
session与connection,是多对一关系,每个session都有一个与之对应的connection,一个connection不同时刻可以提供多个session使用。
把对象保存在关系数据库中需要调用session的各种方法,如:save(),update(),delete(),createQuery()等。
3.transaction简介
hibernate对数据的操作都是封装在事务当中,并且默认是非自动提交的方式。所以用session保存对象,如果不开启事务,并且手工提交事务,对象并不会真正保存在数据库中。
如果想让hibernate想jdbc那样自动提交事务,必须调用session对象的doWork()方法,获得jdbc的connection后,设置其为自动提交事务模式(通常不这样做)。
@Test
public void testSaveStudents() {
Students s = new Students(1, "张三", "男", new Date(), "老君山");
session.doWork(new Work(){
@Override
public void execute(Connection arg0) throws SQLException {
// TODO Auto-generated method stub
arg0.setAutoCommit(true);
}
});
// 保存对象进入数据库
session.save(s);
session.flush();
}
4.session详解
获得session对象的方法
- openSession
- getCurrentSession
这两种方法都来自SessionFactory
如果使用getCurrentSession需要在hibernate.cfg.xml文件中进行配置:
如果是本地事务(jdbc事务)
<propertyname="hibernate.current_session_context_class">thread</property>
如果是全局事务(jta事务)
<propertyname="hibernate.current_session_context_class">jta</property>
例子:
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.Test;
public class SessionTest {
@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 session = sessionFactory.openSession();
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对象
Session session = sessionFactory.getCurrentSession();
if (session != null) {
System.out.println("session创建成功!");
} else {
System.out.println("session创建失败!");
}
}
}
testGetCurrentSession()测试方法必须要在hhibernate.cfg.xml中添加一句
<property name="hibernate.current_session_context_class">thread</property>
openSession与getCurrentSession的区别
- getCurrentSession在事务提交或者回滚之后会自动关闭,而openSession需要手动关闭。如果使用openSession而没有手动关闭,多次之后会导致连接池溢出。
- openSession每次创建新的session对象,getCurrentSession使用现有的session对象。
5.对象关系映射常用配置
<hibernate-mapping
schema="schemaName" //设置模式名子
catalog="catalogName" //设置目录名称
default-cascade="cascade_style" //级联风格
default-access="field|property|ClassName" //访问策略
default-lazy="true|false" //加载策略
package="packagename" //默认包名
/>
<class
name="ClassName"
table="tableName"
batch-size="N" //抓取策略,一次可以抓取的记录条数
where="condition" //抓取条件
entity-name="EntityName" //支持一个类映射成多个表
/>
<id //用id标签代表的是主键
name="propertyName"
type="tpename"
column="column_name" //表中字段名称
length="length"
<generator class="genertorClass"/> //主键生成策略
/>
主键生成策略
标识符生成器 | 描述 |
increment(常用) | 适用于代理主键。由Hibernate自动以递增方式生成。 |
identity(常用) | 适用于代理主键。由底层数据库生成据标识符。 |
sequence(常用) | 适用于代理主键。Hibernate根据底层数据库的序列生成标识符,这要求底层数据库支持序列 |
hilo | 适用于代理主键。Hibernate分局hight/low算法生成表示符 |
seqhilo | 适用于代理主键。使用一个高/低位算法来搞笑的生成long,short或者int类型的标识符 |
native(最常用) | 适用于代理主键。根据底层数据库对自动生成标识符的方式,自动选择identity,sequence或hilo。 |
uuid.hex | 适用于代理主键。Hibernate采用128位的UUID算法生成标识符。 |
uuid.string | 适用于代理主键。UUID被编码成一个16字符长的字符串。 |
assigned(最常用) | 适用于自然主键。有Java用用程序负责生成标识符。 |
foreign | 适用于代理主键。使用灵位一个相关联的对象的标识符。 |
第三天:Hibernate单表操作
1.单一主键
由一列充当主键。
以MySQL为例
- assigned 由java应用程序负责生成(手工赋值)。
- native 由底层数据库自动生成标识符,如果是MySQL就是increment,如果是Oracle就是sequence,等等。
2.基本类型
Hibernate映射类型 | java类型 | 标准SQL类型 | 大小 |
integer/int | java.lang.Integer/int | INTEGER | 4字节 |
long | java.lang.Long/long | BIGINT | 8字节 |
short | java.lang.Short/short | SMALLINT | 2字节 |
byte | java.lang.Byte/byte | TINYINT | 1字节 |
float | java.lang.Float/float | FLOAT | 4字节 |
double | java.lang.Double/double | DOUBLE | 8字节 |
big_decimal | java.math.BigDecimal | NUMERIC | |
character | java.lang.Character/java.lang.String/char | CHAR(1) | 定长字符 |
string | java.lang.String | VARCHAR | 变长字符 |
boolean/ yes_no/true_false | java.lang.Bolean/Boolean | BIT | 布尔类型 |
date | java.util.Date/java.sql.Date | DATE | 代表日期:yyyy-MM-dd |
time | java.util.Date/java.sql.Time | TIME | 代表时间:hh:mi:ss |
timestamp | java.util.Date/java.util.Timestamp | TIMESTAMP | 代表时间和日期:yyyymmddhhmiss |
calendar | java.util.Calendar | TIMESTAMP | 同上 |
calendar_date | java.util.Calendar | DATE | 日期:yyyy-MM-dd |
3.对象类型
映射类型 | Java类型 | 标准SQL类型 | MYSQL类型 | Oracle类型 |
binary | byte[] | VARCHAR(或BLOB) | BLOB | BLOB |
text | java.lang.String | CLOB | TEXT | CLOB |
colb | java.sql.Clob | CLOB | TEXT | CLOB |
blob | java.sql.Blob | BLOB | BLOB | BLOB |
Mysql不支持标准SQL的CLOB类型,在Mysql中,用TEXT,MEDIUMTEXT及LONGTEXT类型来表示长度超过255的长文本数据。
private Blob picture;//照片
public Blob getPicture() {
return picture;
}
public void setPicture(Blob picture) {
this.picture = picture;
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Blob;
import java.sql.SQLException;
import java.util.Date;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
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();
// 开启事务
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);
}
@Test
public void testWriteBlob() throws IOException{
Students s = new Students(1, "张三", "男", new Date(), "老君山");
//先获得照片文件File.separator为路径分割符
File f=new File("e:"+File.separator+"1.jpg");
//获得照片文件输入流
InputStream input =new FileInputStream(f);
//创建一个Blob对象
Blob image=Hibernate.getLobCreator(session).createBlob(input,input.available());
//设置中照片属性
s.setPicture(image);
//保存学生
session.save(s);
}
@Test
public void testReadBlob() throws SQLException, IOException{
Students s=(Students) session.get(Students.class, 1);
//获得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();
}
}
4.组件属性
实体类中的某个属性属于用户自定义的类的对象
如配置文档中的:name="address"就是一个组件属性。
<component name="address" class="Address">
<property name="postcode" column="POSTCODE"></property>
<property name="phone" column="PHONE"></property>
<property name="address" column="ADDRESS"></property>
</component>
5.单表操作CRUD实例
- save (保存)
- update(修改)
- delete(删除)
- get/oad(查询单个记录)
@Test
public void testGetStudents(){
Students s=(Students) session.get(Students.class, 1);
System.out.println(s);
}
@Test
public void testLoadStudent(){
Students s=(Students) session.load(Students.class, 1);
System.out.println(s);
}
@Test
public void testUpdateStudents(){
Students s=(Students) session.get(Students.class, 1);
s.setGender("女");
session.update(s);
}
@Test
public void testDeleteStudents(){
Students s=(Students) session.get(Students.class, 1);
session.delete(s);
}
get与load的区别
在不考虑缓存的情况下,get方法会在调用之后立即向数据库发出sql语句,返回返回持久化对象。
load方法会在调用后返回一个代理对象。
该代理对象只保存了实体对象的id,直到使用对象的非主键属性时才会发出sql语句。
查询数据库中不存在的数据时,get方法返回null,
load方法抛出异常org.hibernate.ObjectNotFoundException。