Hibernate
一、Hibernate概述
Hibernate是使用在三层架构中的dao层的一个框架,与JDBC和myBatis是类似的技术,它也是基于ORM(对象关系映射:数据表中的字段和实体类中的属性一一对应)设计的,其实就是对JDBC的封装,封装之后的东西使用起来更加方便快捷。
Hibernate是一个全自动的ORM框架,而myBatis是一个半自动的ORM框架,全自动代表数据表,SQL语句会自动生成,弊端在于不够灵活,效率低,而mybatis可以字节写sql语句非常灵活。国内更加青睐于myBatis。半自动表示,数据查出来之后可以自动封装到JavaBean(实体类/pojo/entity)中。
JavaBean:类中的属性全部私有,必须有一个无参的构造方法,必须有get和set方法
我们需要通过反射调用无参构造创建对象并且调用set方法给对象赋值,完成数据的自动注入。
二、Hibernate快速入门
2.1、导包
2.2、创建实体类
创建一个User类
2.3、创建实体类的映射文件
注:建议写在实体类包下,名字为实体类名.hbm.xml
约束到资料中的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">
<hibernate-mapping>
<!-- 1 配置实体类的映射文件
使用class标签:将数据表和实体类一一对应,可以参考mybatis中的resultMap标签
name:实体类的全路径
table:表名,可以在核心配置文件中设置自动在数据库中生成表,要保证对应的数据库存在
-->
<class name="com.zhiyou100.javabean.User" table="tb_user">
<!--2 配置主键映射: 使用id标签
column:数据表中的字段名 (可以不写默认与name属性值一样)
name:实体类中的属性名
type:字段的数据类型 (可以不写,会自动根据实体类匹配)
-->
<id name="u_id">
<!--
设置主键生成策略:
increment:主键按数值顺序递增,用在mysql上
sequence:采用数据库提供的sequence 机制生成主键。如Oralce中的Sequence
native:由 Hibernate 根据使用的数据库自行判断,可以自己判断出使用的数据库是oracle还是mysql
-->
<generator class="native"></generator>
</id>
<!-- 3 配置其他字段的映射 -->
<property name="u_name"/>
<property name="u_pass"/>
</class>
</hibernate-mapping>
2.4、创建核心配置文件
要求:创建在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 name=“hibernate.connection.driver_class”>com.mysql.jdbc.Driver</property>
<!-- 如果数据库连接的本机并且端口是3306可以直接写成jdbc:mysql:///数据库名 -->
<property name=“hibernate.connection.url”> jdbc:mysql:///hibernate</property>
<property name=“hibernate.connection.username”>root</property>
<property name=“hibernate.connection.password”>123</property>
<!–第二部分:hibernate部分 -->
<!-- 是否自动生成表:
update:无表创建表,有表修改表
–>
<property name=“hibernate.hbm2ddl.auto”>update</property>
<!-- 是否打印sql -->
<property name=“hibernate.show_sql”>true</property>
<!-- 设置是否格式化–>
<property name=“hibernate.format_sql”>true</property>
<!–第三部分:实体类映射文件部分 -->
<mapping resource=“com/zhiyou100/javabean/User.hbm.xml”/>
</session-factory>
</hibernate-configuration>
2.5、测试
注:在创建工厂的时候就会去创建数据库,这里是非常消耗资源的,我们可以把创建工厂的过程封装起来,只运行一次。最后我们需要使用的是session对象,并且封装之后方法要返回一个session对象提供给我们使用
package com.zhiyou100.test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.zhiyou100.javabean.User;
//注意:使用单元测试时,类名不要写成test
public class HibernateTest {
private static SessionFactory sessionFactory;
private Session session;
//创建sessionFactory
static{
//读取文件并且创建SessionFactory对象
sessionFactory=new Configuration().configure().buildSessionFactory();
}
//创建方法获取session对象
//@Before注解下的方法会在Test下的方法执行前执行
@Before
public void getSession(){
System.out.println("before++++++++++++");
session= sessionFactory.openSession();
}
//关闭资源session
//在test执行之后执行
@After
public void closeSession(){
System.out.println("after--------------");
//判断session是否为null
if (session!=null) {
//关闭session
session.close();
}
}
//添加用户
@Test
public void addUser(){
// 1创建configuration对象
Configuration configuration = new Configuration();
//读取配置文件,如果我们将配置文件写在src下并且名字是hibernate.cfg.xml,可以直接读取到
configuration.configure();
// 2创建Sessionfactory对象
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 3通过SessionFactory创建Session对象
Session session = sessionFactory.openSession();
// 4开启事务
Transaction transaction = session.beginTransaction();
// 5添加用户
// 注:Hibernate不用写sql,操作的都是对象
User user = new User();
//设置名字
user.setU_name("小丽add");
//设置密码
user.setU_pass("12345612");
//添加
session.save(user);
//提交事务
transaction.commit();
//关闭资源
session.close();
sessionFactory.close();
}
//查询一个用户
@Test
public void queryUser(){
//查询id=1的用户
User user=session.get(User.class,1);
//输出
System.out.println(user);
}
//修改
//1)先查询 2)后修改
@Test
public void updateUser(){
//开启事务
Transaction transaction = session.beginTransaction();
//查询
User user = session.get(User.class, 7);
//修改
user.setU_pass("111111234");
session.update(user);
session.clear();
//提交事务
transaction.commit();
}
//删除
@Test
public void deleteUser(){
//开启事务
Transaction transaction = session.beginTransaction();
//查询
User user = session.get(User.class, 7);
//删除
session.delete(user);
//提交事务
transaction.commit();
}
}
三、CRUD
CRUD:创建、读(查询)、修改、删除
private static SessionFactory sessionFactory; private Session session;
//创建sessionFactory static{ //读取文件并且创建SessionFactory对象 sessionFactory=new Configuration().configure().buildSessionFactory(); } //创建方法获取session对象 //@Before注解下的方法会在Test下的方法执行前执行 @Before public void getSession(){ System.out.println("before++++++++++++"); session= sessionFactory.openSession(); } //关闭资源session //在test执行之后执行 @After public void closeSession(){ System.out.println("after--------------"); //判断session是否为null if (session!=null) { //关闭session session.close(); } }
3.1、添加
参考上边案例使用session.save(Object);
3.2、查询
//查询一个用户
@Test
public void queryUser(){
//查询id=1的用户
User user=session.get(User.class,1);
//输出
System.out.println(user);
}
3.3、修改
//修改
//1)先查询 2)后修改
@Test
public void updateUser(){
//开启事务
Transaction transaction = session.beginTransaction();
//查询
User user = session.get(User.class, 7);
//修改
user.setU_pass("111111");
session.update(user);
session.clear();
//提交事务
transaction.commit();
}
3.4、删除
//删除
@Test
public void deleteUser(){
//开启事务
Transaction transaction = session.beginTransaction();
//查询
User user = session.get(User.class, 8);
//删除
session.delete(user);
//提交事务
transaction.commit();
}
四、单元测试
使用到的注解:@Test @Before @After
3.5、总结
添加:save
修改:update
查询:get
删除:delete
五、xml文件没有提示的解决方法
引入dtd文件即可
注:写xml文件时使用快捷键自动生成,千万不要手写,容易出错
过程:
1)复制约束网址,只粘贴内容不要粘贴引号
2)选择图下内容
六、Hibernate对象的状态
Hibernate都是操作对象,间接的操作数据库。 其中对象有三种状态
注:session查询出来的对象其实有一个缓存, 就是缓存在session中
6.1、持久态
特点:保存在数据库中,并且存在了session缓存中
6.2 瞬/临时态
特点:刚new出来的,还没有存到数据库中
6.3、脱管态/游离态
特点:不能直接获取,存在于数据库中但是不在session缓存中。
比如:clear之后就是游离态的
6.4、saveOrUpdate方法
*注:*在创建工厂的时候就会去创建数据库中的表,这里是非常消耗资源的。 所以我们可以把创建工厂的过程封装起来,只运行一次。最后我们需要使用的是session对象,并且封装之后方法要返回一个session对象提供给我们使用。
(因为创建表是在创建sessionFactory的时候创建的,每创建一次表就会创建一次sessionFactory对象,所以可以把它定义为一个静态代码块)
package com.zhiyou100.test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.zhiyou100.javabean.User;
public class SaveOrUpdateTest {
private static SessionFactory sessionFactory;
private Session session;
//创建sessionFactory
static{
//读取文件并且创建sessionFactory对象
sessionFactory=new Configuration().configure().buildSessionFactory();
}
//创建方法获取session对象
//@Before注解下的方法:在单元测试Test下的方法执行前执行
@Before
public void getSession(){
System.out.println("++++++++++++++++");
session=sessionFactory.openSession();
}
//关闭资源
//@After注解下的方法:在单元测试Test方法执行之后执行
@After
public void closeSession(){
System.out.println("-------------");
if (session!=null) {
session.close();
}
}
//持久态对象
@Test
public void chijiu(){
//开启事务
Transaction transaction = session.beginTransaction();
//获取对象
User user = session.get(User.class, 5);
user.setU_name("小气鬼");
session.saveOrUpdate(user);
session.clear();//清空session缓存
//提交事务
transaction.commit();
}
//瞬/临时态对象
@Test
public void shunshi(){
//开启事务
Transaction transaction = session.beginTransaction();
//获取对象
User user = new User();
//user.setU_id(12);
user.setU_name("包子");
user.setU_pass("000000");
session.saveOrUpdate(user);
//提交事务
transaction.commit();
}
//脱管态/游离态对象
@Test
public void youli (){
//开启事务
Transaction transaction = session.beginTransaction();
//获取对象
User user = new User();
//user.setU_id(15); 数据库中不存在这个Id,会报错
user.setU_id(10);
user.setU_name("panda");
user.setU_pass("123123");
//调用方法
session.saveOrUpdate(user);
//提交事务
transaction.commit();
}
}
6.4.1、持久态
做的是修改操作。 如果使用clear方法,会从持久态对象转换成托管态对象
6.4.2、瞬/临时态
id不存在
做的是添加操作。 从瞬时态转换为持久态
6.4.3、托管/游离态
1)该id不存在, 会 报错
2)该id存在
saveOrUpdate方法做的是修改操作。
3)save方法
保存,但是主键还是按照数据库自动递增,会从托管态变成持久态。
Hibernate对象状态之间的转换关系图:
七、HQL
HQL(Hibernate Query Language)就是Hibernate框架的查询语言,SQL操作的是表,HQL操作的是对象。
package com.zhiyou100.test;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.zhiyou100.javabean.User;
public class HQLTest {
private static SessionFactory sessionFactory;
private Session session;
static{
sessionFactory=new Configuration().configure().buildSessionFactory();
}
@Before
public void getSession(){
System.out.println("++++++++++++++");
session=sessionFactory.openSession();
}
@After
public void closeSession(){
System.out.println("-------------");
if (session!=null) {
session.close();
}
}
//查询所有
@Test
public void query1(){
String hql="FROM User";
//查询
Query query = session.createQuery(hql);
//获取数据
List<User> list = query.list();
//打印
for (User user : list) {
System.out.println(user);
}
}
//条件查询
@Test
public void query2(){
String hql="FROM User WHERE u_name=? AND u_pass=?";
//查询
Query query = session.createQuery(hql);
//替换占位符(从0开始)
query.setParameter(0, "小花");
query.setParameter(1, "123456");
//获取数据
List<User> list = query.list();
//打印
for (User user : list) {
System.out.println(user);
}
}
//模糊查询
@Test
public void query3(){
String hql="FROM User WHERE u_name LIKE ?";
//查询
Query query = session.createQuery(hql);
//给占位符赋值
query.setParameter(0, "%小%");
//获取数据
List<User> list = query.list();
//打印结果
for (User user : list) {
System.out.println(user);
}
}
//排序查询
@Test
public void query4(){
//降序排序
String hql="FROM User ORDER BY u_id desc";
//asc 升序排序 desc:降序
Query query = session.createQuery(hql);
//获取数据
List<User> list = query.list();
//打印
for (User user : list) {
System.out.println(user);
}
}
//分页排序
@Test
public void query5(){
String hql="FROM User";
//查询
Query query = session.createQuery(hql);
//设置起始位置(从0开始的)
query.setFirstResult(0);
//设置每页数据量
query.setMaxResults(4);
//获取数据
List<User> list = query.list();
//打印结果:
for (User user : list) {
System.out.println(user);
}
}
//投影查询:只查询部分字段
@Test
public void query6(){
//注:实体类中必须有对应的构造方法
String hql="SELECT new User(u_name,u_pass) FROM User";
Query query = session.createQuery(hql);
List<User> list = query.list();
for (User user : list) {
System.out.println(user);
}
}
//自定义sql语句
@Test
public void query(){
//定义sql语句
String sql="select * from tb_user"; //查询的是数据库中的表
//使用方法查询
SQLQuery sqlQuery = session.createSQLQuery(sql);
sqlQuery.addEntity(User.class);
//转换成集合
List<User> list = sqlQuery.list();
//打印
for (User user : list) {
System.out.println(user);
}
}
}
7.1、查询所有
//查询所有 @Test public void query1(){ String hql="FROM User"; //查询 Query query = session.createQuery(hql); //获取数据 List<User> list = query.list(); //打印 for (User user : list) { System.out.println(user); }
}
7.2、条件查询
//条件查询 @Test public void query2(){ String hql="FROM User WHERE u_name=? AND u_pass=?"; //查询 Query query = session.createQuery(hql); //替换占位符(从0开始) query.setParameter(0, "小花"); query.setParameter(1, "123456"); //获取数据 List<User> list = query.list(); //打印 for (User user : list) { System.out.println(user); }
}
7.3、模糊查询
//模糊查询
@Test
public void query3(){
String hql="FROM User WHERE u_name LIKE ?";
//查询
Query query = session.createQuery(hql);
//给占位符赋值
query.setParameter(0, "%小%");
//获取数据
List<User> list = query.list();
//打印结果
for (User user : list) {
System.out.println(user);
}
}
7.4、降序排序
//排序查询 @Test public void query4(){ //降序排序 String hql="FROM User ORDER BY u_id desc"; //asc 升序排序 desc:降序 Query query = session.createQuery(hql); //获取数据 List<User> list = query.list(); //打印 for (User user : list) { System.out.println(user); }
}
7.5、分页查询
//分页排序
@Test
public void query5(){
String hql="FROM User";
//查询
Query query = session.createQuery(hql);
//设置起始位置(从0开始的)
query.setFirstResult(0);
//设置每页数据量
query.setMaxResults(4);
//获取数据
List<User> list = query.list();
//打印结果:
for (User user : list) {
System.out.println(user);
}
}
7.6、投影查询
投影查询:只查询部分字段
注:实体类中必须有对应的构造方法
//投影查询:只查询部分字段
@Test
public void query6(){
//注:实体类中必须有对应的构造方法
String hql="SELECT new User(u_name,u_pass) FROM User";
Query query = session.createQuery(hql);
List<User> list = query.list();
for (User user : list) {
System.out.println(user);
}
}
八、SQL
Hibernate中也可以写sql语句,但是非常滴麻烦
我们使用createSQLQuery方法实现
//自定义sql语句
@Test
public void query(){
//定义sql语句
String sql="select * from tb_user"; //查询的是数据库中的表
//使用方法查询
SQLQuery sqlQuery = session.createSQLQuery(sql);
sqlQuery.addEntity(User.class);
//转换成集合
List<User> list = sqlQuery.list();
//打印
for (User user : list) {
System.out.println(user);
}
九、学习中出现的问题
单元测试:
1)方法不能有返回值,不能有参数,不能被static修饰,不能使用private修饰
2)在类中运行方法,右击直接运行会运行所有的Test方法。 所以点击单个的方法名运行单个方法即可
注意:单词别写错
空指针(看一下是否创建了session对象)
乱码:创建数据库时选择UTF8,以免出现乱码现象
查看当前文件的编码格式:Alter+回车
十、学习要求
10.1、整理一个自己的学习笔记
10.2、Hibernate基础知识,配置和HQL语句熟练掌握
10.3、Hibernate一对多,多对多配置了解
</div>
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-258a4616f7.css" rel="stylesheet">
</div>