Hibernate
JavaEE 三层架构
web 层:Struts2 框架
service 层:Spring 框架
dao 层: Hibernate 框架
- 对数据库进行 crud 操作
Hibernate
- 应用在三层架构 中的 dao 层框架
- 对数据库进行 crud 操作 ,就是对jdbc 的封装,不需要写复杂的jdbc代码了
- 开源的轻量级框架
- 非侵入式框架
- 全自动的 ORM 关系映射框架
- 对于一些成熟 不经常变动的项目 变动较小的项目
ORM 思想
object relational mapping :对象关系映射
- 让实体类和数据库表进行 对应关系
- 不需要直接操作数据库表 而操作表对应的实体对象
Hibernate 环境搭建
- 导入jar包
- 创建实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class t_userModel {
private int rid ;
private String login_name;
private String password;
private String u_name;
}
-
配置实体类和数据库表 – 对应关系 (映射关系)
- 使用配置文件的方式实现 在实体类所在包里面创建 实体类名称.hbm.xml
<?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"> <hibernate-mapping> <!--name: 类的全限定名 table:指的是类所对应的表--> <class name="com.zhang.model.t_userModel" table="t_user"> <!--name:指的是类属性 type:类的类属性类型 column:表列列段--> <id name="rid" type="java.lang.Integer" column="rid"> <!--class:指的是数据库表的主键生成策略 increment:自动生成--> <generator class="navite"></generator> </id> <property name="login_name" type="java.lang.String" column="login_name"/> <property name="password" type="java.lang.String" column="password"/> <property name="u_name" type="java.lang.String" column="u_name"/> </class> </hibernate-mapping>
- 创建 Hibernate 核心配置文件
- 位置 : 必须在 src 下面
- 名称: 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配置文件的开始--> <hibernate-configuration> <!--表明以下的配置是针对session-factory配置的,SessionFactory是Hibernate中的一个类, 这个类主要负责保存HIbernate的配置信息,以及对Session的操作--> <session-factory> <!--配置数据库的驱动程序--> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate?useUnicode=true&characterEncoding=utf-8</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">123456</property> <!--数据库连接池的大小--> <property name="hibernate.connection.pool.size">20</property> <!-- 是否在后台显示Hibernate用到的SQL语句,开发时设置为true,便于差错, 程序运行时可以在Eclipse的控制台显示Hibernate的执行Sql语句。项目部署后可以设置为false,提高运行效率 --> <property name="hibernate.show_sql">true</property> <!--输出底层sql 语句--> <property name="hibernate.format_sql">true</property> <!--update 如果表存在则更新 否则 创建--> <property name="hibernate.hbm2ddl.auto">update</property> <!-- jdbc.fetch_size是指Hibernate每次从数据库中取出并放到JDBC的Statement中的记录条数 。Fetch Size设的越大,读数据库的次数越少,速度越快,Fetch Size越小,读数据库的次数越多,速度越慢 --> <property name="jdbc.fetch_size">50</property> <!-- jdbc.batch_size是指Hibernate批量插入,删除和更新时每次操作的记录数。 Batch Size越大,批量操作的向数据库发送Sql的次数越少,速度就越快,同样耗用内存就越大 --> <property name="jdbc.batch_size">23</property> <!--jdbc.use_scrollable_resultset是否允许Hibernate用JDBC的可滚动的结果集。对分页的结果集。对分页时的设置非常有帮助--> <property name="jdbc.use_scrollable_resultset">false</property> <!--connection.useUnicode连接数据库时是否使用Unicode编码--> <property name="Connection.useUnicode">true</property> <!--connection.characterEncoding连接数据库时数据的传输字符集编码方式,最好设置为gbk,用gb2312有的字符不全--> <property name="connection.characterEncoding">gbk</property> <!--hibernate.dialect 只是Hibernate使用的数据库方言,就是要用Hibernate连接那种类型的数据库服务器。--> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!--实现 hibernate 与本地 session 对象 绑定--> <property name="hibernate.current_session_context_class">thread</property> <!--指定映射文件--> <mapping resource="com/zhang/model/t_userModel.hbm.xml"/> </session-factory> </hibernate-configuration>
实现 crud
- 加载 hibernate 核心配置文件
- 创建 SessionFactory 对象
- 使用 SessionFactory 创建 Session 对象
- 开启事务
- crud 操作
- 提交事务
- 关闭资源
添加:调用 session.save(对象); 方法实现
@Test
public void t1(){
// - 加载 hibernate 核心配置文件
Configuration cfg = new Configuration().configure();
// - 创建 SessionFactory 对象 根据映射关系在 配置的数据库中创建表
SessionFactory sessionFactory = cfg.buildSessionFactory();
// - 使用 SessionFactory 创建 Session 对象
Session session = sessionFactory.openSession();
// - 开启事务
Transaction transaction = session.beginTransaction();
// - crud 操作
// 添加
t_userModel tUser = new t_userModel();
tUser.setLogin_name("xiao");
tUser.setPassword("123456");
tUser.setU_name("xiao");
session.save(tUser);
// - 提交事务
transaction.commit();
// - 关闭资源
session.close();
sessionFactory.close();
}
工具类
public class hibernateUtil {
static Configuration cfg = null;
static SessionFactory sessionFactory = null;
//静态代码块实现
static {
//加载核心配置文件
cfg = new Configuration().configure();
sessionFactory = cfg.buildSessionFactory();
}
//提供方法返回 SessionFactory
public static SessionFactory getSessionFactory(){
return sessionFactory;
}
}
主键生成 策略:
native:主键自动增长 根据使用的数据库选择生成那个值
uuid:生成32位 uuid 值
根据id查询对象
session.get(t_userModel.class, 1000); //第一个参数表示: 查询返回的对象 第二个:id
@Test
public void selById(){
//使用工具类生成
SessionFactory sessionFactory = hibernateUtil.getSessionFactory();
// - 使用 SessionFactory 创建 Session 对象
Session session = sessionFactory.openSession();
// - 开启事务
Transaction transaction = session.beginTransaction();
//根据id查询对象
// 第一个参数表示: 查询返回的对象 第二个:id
t_userModel model = session.get(t_userModel.class, 1000);
System.out.println(model);
// - 提交事务
transaction.commit();
// - 关闭资源
session.close();
sessionFactory.close();
}
修改
//先根据id查询 在修改
//根据id查询对象
t_userModel model = session.get(t_userModel.class, 1000);
//修改后的值
model.setU_name("小灰灰");
model.setU_phone("12345678911");
//修改
session.update(model);
删除
//先根据id查询 在删除
//根据id查询对象
t_userModel model = session.get(t_userModel.class, 1005);
//删除
session.delete(model);
实体类对象状态
瞬时态:对象里面没有id值,对象与session没有关联
持久态:对象里面有id 值,对象与session 有关联
托管态:对象里面有id 值,对象与session 没有关联
saveOrUpdate
session.saveOrUpdate(对象);
如果是 瞬时态 调用会执行 save 方法
如果是 持久态,托管态 调用会执行 update方法
一级缓存
把数据放在内存中 提高读取效率
特点:
- 一级缓存 默认是打开的
- 一级缓存 使用范围 session 范围
- 一级缓存中 存储的数据必须是持久态数据
二级缓存:
目前已经不使用了 被 redis 替代了
事务
hibernate 中事务的规范写法:
@Test
public void selByIdGF(){
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
sessionFactory = hibernateUtil.getSessionFactory();
session = sessionFactory.openSession();
// 开启事务
transaction = session.beginTransaction();
//根据id查询对象
t_userModel model = session.get(t_userModel.class, 1000);
System.out.println(model);
// - 提交事务
transaction.commit();
}catch (Exception e){
e.printStackTrace();
//回滚事务
transaction.rollback();
}finally {
// - 关闭资源
session.close();
sessionFactory.close();
}
}
hibernate 绑定 session
hibernate.cfg.xml
<!--实现 hibernate 与本地 session 对象 绑定-->
<property name="hibernate.current_session_context_class">thread</property>
hibernateUtil
//返回与本地线程绑定的 session 对象
public static Session getSessionObject(){
return sessionFactory.getCurrentSession();
}
@Test
public void selByIdSession(){
Session session = null;
Transaction transaction = null;
try {
//获取到与本地线程绑定的session
session = hibernateUtil.getSessionObject();
// 开启事务
transaction = session.beginTransaction();
//根据id查询对象
t_userModel model = session.get(t_userModel.class, 1000);
System.out.println(model);
// - 提交事务
transaction.commit();
}catch (Exception e){
e.printStackTrace();
//回滚事务
transaction.rollback();
}finally {
// - 关闭资源
session.close();
}
}
查询
Query
使用 Query 对象 ,不需要写sql 语句 但是要写 hql 语句
hql 语句: hibernate query language : hibernate 提供的查询语句
sql 与 hql 区别
sql 操作 表和表字段
hql 操作 实体类 和 属性
hql 语句 :
from 实体类 where 属性名 =: 参数名
//创建 Query 对象 方法里面的参数是 hql 语句
Query query = session.createQuery("from t_userModel");
List list = query.list();
list.forEach(System.out::println);
Criteria
//创建 Criteria 对象 方法里面的参数是实体类
Criteria criteria = session.createCriteria(t_userModel.class);
List list = criteria.list();
list.forEach(System.out::println);
SQLQuery
//创建 SQLQuery 对象 方法里面的参数是 普通sql 语句 得到的是 数组
SQLQuery sqlQuery = session.createSQLQuery("select * from t_user");
List<Object[]> list = sqlQuery.list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
一对一
<!-- 其中主表的配置 -->
<one-to-one name="主表对象中子表对象的属性名" class="子表对象的类名"cascade="save-update"/>
<!-- 子表的配置 -->
<one-to-one name="子表对象中主表对象的属性名" class="主表对象的类名" constrained="true" />
一对多关系
<set name="java映射类中对应的属性" inverse="true" lazy="true">
<key column="表中对应字段"/>
<one-to-many class="多方的类"/>
</set>
<many-to-one name="java映射类中对应的属性" column="表中对应字段" class="类名" not-null="true" />
多对多关系
<set name="java对象的属性名" table="表名" cascade="all" outer-join="false">
<key column="表的对应字段"/>
<many-to-many class="另一个表的对象类" column="另一个表的字段"/>
</set>