hibernate入门
1、ORM框架:object relational mapping用于实现面向对象编程语言里不同数据类型系统的数据之间的转换。
Hibernate是一个数据持久化层的ORM框架.它是轻量级的JavaEE应用的持久层解决方案,是一个关系数据库ORM框架
ORM 就是通过将Java对象映射到数据库表,通过操作Java对象,就可以完成对数据表的操作
Hibernate提供了对关系型数据库增删改成操作
hibernate的优点:
- Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码
- Hibernate是一个基于jdbc的主流持久化框架,是一个优秀的orm实现,它很大程度的简化了dao层编码工作 session.save(User);
- Hibernate使用java的反射机制
- Hibernate的性能非常好,因为它是一个轻量级框架。映射的灵活性很出色。它支持很多关系型数据库,从一对一到多对多的各种复杂关系
入门案例:
1、编写流程
- 导入jar包
- 创建数据库和表
- 编写核心配置文件(hibernate.cfg.xml)–> 配置获得链接等参数
- 编写映射文件 hibernate mapping(*.hbm.xml)
- 使用api测试
一、创建表
create database h_db;
use h_db;
create table t_user(
id int auto_increment primary key,
username varchar(50),
password varchar(30)
);
二、导入jar包:
- hibernate3.jar
- \lib\required
- jap规范:lib\jpa
- mysql驱动包
包的含义:
三、编写JavaBean + 映射文件
package com.zeroyoung.domain;
public class User {
/*
* create table t_user(
id int auto_increment primary key,
username varchar(50),
password varchar(30)
);
*/
private Integer uid;
private String username;
private String password;
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [uid=" + uid + ", username=" + username + ", password="
+ password + "]";
}
}
在javabean的同一目录下创建一个User.hbm.xml的文件
这个xml的文件的约束在hibernate3.jar/org.hibernate/hibrenate-mapping-30.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- ORM元数据,表对象关系映射文件
package:配置改配置文件中类所在的包 -->
<hibernate-mapping >
<!-- class: 配置实体与表的关系
name : 填写实体的完整类名
table: 与实体对应表的名称
dynamic-insert:动态插入 默认值是false
true=>如果字段值为null,不参与insert语句
dynamic-update:动态更新 默认值"false"
true=> 没改动过的属性,将不会生成到update语句中
-->
<class name="com.zeroyoung.domain.User" table="t_user">
<!-- 主键的声明 -->
<!-- id: 配置实体与表中 id对应
name: user对象中标识主键的属性名称
column: 主键在表中的列名
length: 列的数据长度
unsaved-value(不常用): 指定主键为什么值时,当做null来处理.
access(强烈推荐不要用):field 那么在操作属性时,会直接操作对应的字段而不是get/set方法
-->
<id name="uid" column="id" length="255">
<!-- 主键生成策略,由数据库控制 -->
<!-- generator:主键生成策略
1.increment 数据库自己生成主键. 先从数据库中查询最大的ID值,将ID值加1作为新的主键
2.identity 依赖于数据的主键自增功能
3.sequence 序列,依赖于数据中的序列功能(Oracle).
4.hilo(纯了解,永远用不到) : Hibernate自己实现序列的算法,自己生成主键. (hilo算法 )
5.native 自动根据数据库判断,三选一. identity|sequence|hilo
6.uuid 生成32位的不重复随机字符串当做主键
7.assigned 自己指定主键值. 表的主键是自然主键时使用.
-->
<generator class="native"></generator>
</id>
<!-- property : 实体中属性与表中列的对应
name : 实体中属性名称
column : 表中列的名称
length : 数据长度
precision: 小数点后的精度
scale: 有效位数
insert(一般不用): 该属性是否加入insert语句.
update(一般不用): 该属性是否加入update语句.
not-null : 指定属性的约束是否使用 非空
unique : 指定属性的约束是否使用 唯一
-->
<property name="username" column="username"/>
<property name="password" column="password"/>
</class>
</hibernate-mapping>
四、编写核心配置文件
在src目录下面编写配置文件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:元素用于配置hibrenate中的属性,方式为键值对 -->
<!-- hibernate.connection.driver_class:数据库连接驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!--hibernate.connection.username: 数据库连接用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- 数据库连接密码 -->
<property name="hibernate.connection.password">root</property>
<!-- 数据库连接的地址,路径 -->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/h_day01_db</property>
<!-- 操作数据库时,会向控制台打印sql语句 -->
<property name="show_sql">true</property>
<!-- 格式化sql语句 -->
<property name="format_sql">true</property>
<!-- hbm2ddl.auto: 生成表结构的策略配置
update(最常用的取值): 如果当前数据库中不存在表结构,那么自动创建表结构.
如果存在表结构,并且表结构与实体一致,那么不做修改
如果存在表结构,并且表结构与实体不一致,那么会修改表结构.会保留原有列.
create(很少):无论是否存在表结构.每次启动Hibernate都会重新创建表结构.(数据会丢失)
create-drop(极少): 无论是否存在表结构.每次启动Hibernate都会重新创建表结构.每次Hibernate运行结束时,删除表结构.
validate(很少):不会自动创建表结构.也不会自动维护表结构.Hibernate只校验表结构. 如果表结构不一致将会抛出异常.
-->
<property name="hbm2ddl.auto">update</property>
<!-- 数据库方言配置
org.hibernate.dialect.MySQLDialect (选择最短的)
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- hibernate.connection.autocommit: 事务自动提交 -->
<property name="hibernate.connection.autocommit">true</property>
<!-- 将Session与线程绑定=> 只有配置了该配置,才能使用getCurrentSession -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- 引入ORM 映射文件
填写src之后的路径
-->
<mapping resource="com/zeroyoung/domain/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
五、测试:
@Test
public void tet() {
// 1.加载配置文件获取核心配置核心对象
// 1.1 调用configure() 方法=> 加载src下名为hibernate.cfg.xml
// 1.2 如果配置文件不符合默认加载规则.我们可以调用
// new Configuration().configure(file); 通过file加载
// new Configuration().configure(path); 通过路径加载
// 1.3 可以通过Configuration对象加载 映射文件(不推荐)
// 推荐hibernate.cfg.xml 使用 mapping 属性引入配置文件
// 规范: 1>orm映射文件名称与实体的简单类名一致
// 2>orm映射文件 需要与实体的类在同一包下
Configuration config = new Configuration().configure();
// 2.获取sessionFactory,相当于连接池
// 根据Configuration 配置信息创建 SessionFactory
SessionFactory factory = config.buildSessionFactory();
// 3.获取会话session,相当于serlvet重点connection
// 3.1 openSession => 获得一个全新的Session对象
// 3.2 getCurrentSession => 获得与当前线程绑定的session对象
// 调用getCurrentSession 需要加上一个配置: <property
// name="hibernate.current_session_context_class">thread</property>
Session session = factory.openSession();
User u = new User();
u.setPassword("1233");
u.setUsername("zhon");
// 4.操作数据库
session.save(u);
// 5.关闭资源
session.close();
factory.close();
}
api详解
- Configuration配置对象
我们编写的hibernate.cfg.xml配置文件需要使用 Configuration来加载,加载的方式有几种。常见的使用方式如下:
Configuration config = new Configuration().configure();
这里configure()方法就是加载src下名为hibernate.cfg.xml
同时,它也提供了有参数的构造方法来使用,当我们的配置文件的不符合默认加载规则,我们可以调用如下的方法
- new Configuration().configure(file); 通过file加载
- new Configuration().configure(path); 通过路径加载
####SessionFactory工厂
SessionFactory 相当于java web连接池,用于管理所有session
获得方式:SessionFactory factory = config.buildSessionFactory();
sessionFactory hibernate缓存配置信息 (数据库配置信息、映射文件,预定义HQL语句 等)
SessionFactory线程安全,可以是成员变量,多个线程同时访问时,不会出现线程并发访问问题。
提供api:
打开一个新的会话:
Session session = factory.openSession();
这里得到的session是重新创建的session会话
得到当前线程绑定的session
Session session = getCurrentSession()
这里是使用当前线程绑定的session会话,如果当前线程没绑定session则先创建一个session对象,然后绑定之后返回。
要想使用当前线程绑定session就需要在配置文件中加上这句话:
<property name="hibernate.current_session_context_class">thread</property>
这个方法主要是跟事务的提交有关系,事务关闭时,会自动把与当前线程关联的session关闭,并删除
Session 会话
Session 相当于 JDBC的 Connection – 会话,我们是通过session来操作po(persistent object ,用于与数据库交互数据。–dao层 (JavaBean + hbm ))对象的
session是单线程的,线程不安全,不能编写成员变量
session中的几个api方法:
- save 保存
- update 更新
- delete 删除
- get 通过id查询,如果没有 null
- load 通过id查询,如果没有抛异常
- createQuery(“hql”) 获得Query对象
- createCriteria(Class) 获得Criteria对象
保存对象上面的例子已近说明,更新对象那个的方法如下
User user = (User) session.get(User.class, 1);
user.setUsername("汤姆");
session.update(user);
删除:
// 先查询出你要修改的对象
User user = (User) session.get(User.class, 1);
// 删除
session.delete(user);
get查询:
第一个参数时候javabean,第二个是id的值
// 先查询出你要修改的对象
User user = (User) session.get(User.class, 2);
load查询:
// 先查询出你要修改的对象
User user = (User) session.load(User.class, 2);
load与get的区别:
get方法被调用时立刻 发送sql语句查询、load调用时并没有查询数据库,当我们需要使用该对象的时候,才查询数据
createQuery编写查询语句
查询所有的用户
// HQL语言 => Hibernate Query Language
// createQuery 传入hql语句查询,完整类名字
// 相当于select * from t_user;
Query query = session.createQuery("from com.zeroyoung.domain.User");
List<User> list = query.list();
System.out.println(list);
Criteria查询所有(一般很少使用)
// Criteria 查询 => Hibernate独创的面向对象的查询=> 无语句
Criteria criteria = session.createCriteria(User.class);
List<User> list = criteria.list();
支持原生的sql语句查询:
// 原生的Sql查询
SQLQuery query = session.createSQLQuery("select * from t_user");
// addEntity 将查询结果封装到指定对象中
query.addEntity(User.class);
List<User> list = query.list();
事务Transaction
开启事务 beginTransaction()
获得事务 getTransaction()
提交事务:commit()
回滚事务:rollback()
try{
//开启
//session操作
//提交
} catch(e){
//回滚
}
query对象
通过createQuery()方法,我们会得到一个query对象,它能帮助我们完成一些列的事情。
api:
- list() 查询所有
- uniqueResult()获取一个结果,如果没有查到返回null,如果查询到多条抛出异常
- setFirstResult(int)分页,开始索引的数startIndex
- setMaxResults(int) 分页,每页显示个数 pageSize
Query query = session.createQuery("from com.zeroyoung.domain.User");
// 分页 limit index,count;
// 指定结果从第几个开始拿
query.setFirstResult(0);
// 指定拿几个
query.setMaxResults(2);
// query.list() 将hql语句执行,并返回结果(多行)
List<User> list = query.list();
System.out.println(list);
//uniqueResult 将hql语句执行,并返回结果(一行),用于在createquery中添加条件
//User u = (User) query.uniqueResult();
//System.out.println(u);
Criteria对象
QBC(query by criteria),hibernate提供纯面向对象查询语言,提供直接使用PO对象进行操作。
获得方式:Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.eq("username", "tom"));
// Restrictions.gt(propertyName, value) 大于
// Restrictions.ge(propertyName, value) 大于等于
// Restrictions.lt(propertyName, value) 小于
// Restrictions.le(propertyName, value) 小于等于
// Restrictions.like(propertyName, value) 模糊查询,注意:模糊查询值需要使用 % _
创建一个工具类
public class H3Utils {
// 会话工厂,整个程序只有一份。
private static SessionFactory factory;
static{
//1 加载配置
Configuration config = new Configuration().configure();
//2 获得工厂
factory = config.buildSessionFactory();
//3 关闭虚拟机时,释放SessionFactory
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
System.out.println("虚拟机关闭!释放资源");
sf.close();
}
}));
}
/**
* 获得一个新的session
* @return
*/
public static Session openSession(){
return factory.openSession();
}
/**
* 获得当前线程中绑定session
* * 注意:必须配置
* @return
*/
public static Session getCurrentSession(){
return factory.getCurrentSession();
}
}
配置文件详解
<?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 元素用于配置Hibernate中的属性
键:值
-->
<!-- hibernate.connection.driver_class : 连接数据库的驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- hibernate.connection.username : 连接数据库的用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- hibernate.connection.password : 连接数据库的密码 -->
<property name="hibernate.connection.password">1234</property>
<!-- hibernate.connection.url : 连接数据库的地址,路径 -->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/EE19Day01</property>
<!-- show_sql: 操作数据库时,会 向控制台打印sql语句 -->
<property name="show_sql">true</property>
<!-- format_sql: 打印sql语句前,会将sql语句先格式化 -->
<property name="format_sql">true</property>
<!-- hbm2ddl.auto: 生成表结构的策略配置
update(最常用的取值): 如果当前数据库中不存在表结构,那么自动创建表结构.
如果存在表结构,并且表结构与实体一致,那么不做修改
如果存在表结构,并且表结构与实体不一致,那么会修改表结构.会保留原有列.
create(很少):无论是否存在表结构.每次启动Hibernate都会重新创建表结构.(数据会丢失)
create-drop(极少): 无论是否存在表结构.每次启动Hibernate都会重新创建表结构.每次Hibernate运行结束时,删除表结构.
validate(很少):不会自动创建表结构.也不会自动维护表结构.Hibernate只校验表结构. 如果表结构不一致将会抛出异常.
-->
<property name="hbm2ddl.auto">update</property>
<!-- 数据库方言配置
方言:为不同的数据库,不同的版本,生成sql语句(DQL查询语句)提供依据
mysql 字符串 varchar
orcale 字符串 varchar2
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- hibernate.connection.autocommit: 事务自动提交 -->
<property name="hibernate.connection.autocommit">true</property>
<!-- 将Session与线程绑定=> 只有配置了该配置,才能使用getCurrentSession -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- 引入ORM 映射文件
填写src之后的路径
-->
<mapping resource="com/itheima/a_hello/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Hibernate中持久化类–javabean
1、javabean的编写规范
- 提供一个无参数 public访问控制符的构造器
- 提供一个标识属性,映射数据表主键字段
- 所有属性提供public访问控制符的 set get 方法(javaBean)
- 标识属性应尽量使用基本数据类型的包装类型
- 不要用final修饰实体 (将无法生成代理对象进行优化)
2、持久化对象的唯一标识OID
- java按地区区分同一个类的不同对象
- 关系数据库用主键区分同一条记录
- Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系
结论:对象的OID和数据库的表的主键对应。为保证OID的唯一性,应该让Hibernate来为OID付值
区分自然主键和代理主键
一、主键需要具备:
- 不为空
- 不能重复
不能改变
自然主键:在业务中,某个属性符合主键的三个要求.那么该属性可以作为主键列.
代理主键:在业务中,不存符合以上3个条件的属性,那么就增加一个没有意义的列.作为主键.
基本数据与包装类型
- 基本数据类型和包装类型对应hibernate的映射类型相同
- 基本类型无法表达null、数字类型的默认值为0。
- 包装类默认值是null。当对于默认值有业务意义的时候需要使用包装类。
数据类型的对应图标表
普通属性
<hibernate-mapping>
package 用于配置PO类所在包
例如: package="com.itheima.d_hbm"
<class> 配置 PO类 和 表 之间对应关系
name:PO类全限定类名
例如:name="com.itheima.d_hbm.Person"
如果配置 package,name的取值可以是简单类名 name="Person"
table : 数据库对应的表名
dynamic-insert="false" 是否支持动态生成insert语句
dynamic-update="false" 是否支持动态生成update语句
如果设置true,hibernate底层将判断提供数据是否为null,如果为null,insert或update语句将没有此项。
普通字段
<property>
name : PO类的属性
column : 表中的列名,默认name的值相同
type:表中列的类型。默认hibernate自己通过getter获得类型,一般情况不用设置
取值1: hibernate类型
string 字符串
integer 整形
取值2: java类型 (全限定类名)
java.lang.String 字符串
取值3:数据库类型
varchar(长度) 字符串
int 整形
<property name="birthday">
<column name="birthday" sql-type="datetime"></column>
</property>
javabean 一般使用类型 java.util.Date
jdbc规范提供3中
java类型 mysql类型
java.sql.Date date
java.sql.time time
java.sql.timestamp timestamp
null datetime
以上三个类型都是java.util.Date子类
length : 列的长度。默认值:255
not-null : 是否为null
unique : 是否唯一
access:设置映射使用PO类属性或字段
property : 使用PO类属性,必须提供setter、getter方法
field : 使用PO类字段,一般很少使用。
insert 生成insert语句时,是否使用当前字段。
update 生成update语句时,是否使用当前字段。
默认情况:hibernate生成insert或update语句,使用配置文件所有项
注意:配置文件如果使用关键字,列名必须使用重音符
主键
<id>配置主键
name:属性名称
access="" 设置使用属性还是字段
column="" 表的列名
length="" 长度
type="" 类型
<generator> class属性用于设置主键生成策略
1.increment 由hibernate自己维护自动增长
底层通过先查询max值,再+1策略
不建议使用,存在线程并发问题
2.identity hibernate底层采用数据库本身自动增长列
例如:mysql auto_increment
3.sequence hibernate底层采用数据库序列
例如:oracle 提供序列
4.hilo
</generator>
5.native 根据底层数据库的能力选择 identity、sequence 或者 hilo 中的一个。【】
##以上策略使用整形,long, short 或者 int 类型
6.uuid 采用字符串唯一值【】
##以上策略 代理主键,有hibernate维护。
7.assigned 自然主键,由程序自己维护。【】
本文介绍Hibernate框架的基本概念,包括ORM框架的定义及Hibernate的特点,并详细讲解了如何通过编写JavaBean类和映射文件来实现数据库操作。
193

被折叠的 条评论
为什么被折叠?



