Hibernate学习

运行环境

新建mavenProject工程,引入依赖

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<hibernate.version>5.4.3.Final</hibernate.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.29</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>${hibernate.version}</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate.javax.persistence</groupId>
			<artifactId>hibernate-jpa-2.0-api</artifactId>
			<version>1.0.0.Final</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.16.20</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>

新建实体类,和实体类的配置文件

新建实体类

@NoArgsConstructor
@Data
public class User {
	private Integer id;
	private String name;
	private int age;
	private String address;
}

新建实体类的配置文件

<hibernate-mapping>
	<class name="lamose.entity.User" table="t_user">
		<!-- 配置实体类和表名称对应 -->
		<!-- name为实体类中的属性名,column为表的字段名  -->
		<id name="id" column="id">
			<!-- 自动增长策略 -->
			<generator class="native"></generator>
		</id>
		<!-- 生成其他列 -->
		<property name="name" column="name"></property>
		<property name="age" column="age"></property>
		<property name="address" column="address"></property>
	</class>
</hibernate-mapping>

创建hibernate核心配置文件

<hibernate-configuration>
	<session-factory>
	<!-- 必选 配置数据库信息 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/coulddb02</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">123456</property>
	<!-- 配置hibernate -->
		<!-- 打印Sql语句   -->
		<property name="hibernate.show_sql">true</property>
		<!-- 输出语句的格式  -->
		<property name="hibernate.format_sql">true</property>
		<!-- 创建表 -->
		<!-- update:如果表存在,即更新,如果不存在,则创建 -->
		<property name="hibernate.hbm2ddl.auto">update</property>
		<!-- 数据库方言,例如limit是mySql方言  -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
	<!-- 把映射文件放到核心配置文件中  -->
		<mapping resource="User.hbm.xml"/>
	</session-factory>
</hibernate-configuration>

操作步骤

  1. 加载核心配置文件
  2. 创建SessionFactory对象
  3. 使用SessionFactory创建Session对象
  4. 开启事务
  5. CRUD
  6. 提交事务
  7. 关闭资源
    其中123467为固定操作,第五步写具体的数据库操作
	public void testAdd() {
		// 1、加载核心配置文件
		Configuration cfg = new Configuration();
		cfg.configure();

		// 2、创建SessionFactory对象
		SessionFactory sessionFactory = cfg.buildSessionFactory();

		// 3、使用SessionFactory创建Session对象
		Session session = sessionFactory.openSession();

		// 4、开启事务
		Transaction tx = session.beginTransaction();
		// 5、CRUD
		User user = new User();
		user.setName("lamose").setAge(22).setAddress("China");
		session.save(user);
		// 6、提交事务
		tx.commit();
		// 7、关闭资源
		session.close();
		sessionFactory.close();
	}

Hibernate核心API

Configuration

Configuration cfg = new Configuration();
cfg.configure();
//Configuration cfg = new Configuration().configure("自定义核心配置文件路径");
	

根目录下面找到名称为hibernate.cfg.xml文件,创建对象,把配置文件放到对象中(加载核心配置文件)

SessionFactory

使用Configuration对象创建SessionFactory对象

  1. 创建SessionFactory过程中:
    – 更具核心配置文件中,有数据库配置,有映射文件配置部分,到数据库中根据映射关系完成数据库表的创建
<property name="hibernate.hbm2ddl.auto">update</property>
  1. 在创建SessionFactory过程中,每一次hibernate操作,都会创建或者更新表,这非常消耗资源,解决方法:
public class HibernateUtil {
	static Configuration cfg = null;
	static SessionFactory sessionFactory = null;
	static {
		cfg = new Configuration();
		cfg.configure();
		sessionFactory = cfg.buildSessionFactory();
	}
	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}
}
public void testAdd() {
	SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
	Session session = sessionFactory.openSession();
	Transaction tx = session.beginTransaction();
	User user = new User();
	user.setName("lamose").setAge(22).setAddress("China");
	session.save(user);
	tx.commit();
	session.close();
	sessionFactory.close();
}

Session

1、session类似于jdbc中的connection对象
2、调用session对象中的方法进行CRUD操作

添加: save方法
修改: update方法
删除: delete方法
根据id查询: get方法

3、session对象是单线程对象

session对象不能被共用,只能自己使用

Transaction

1、事务对象

	Transaction tx = session.beginTransaction();

2、事务操作,提交和回滚

	tx.commit();
	tx.rollback();

Hibernate操作数据库

Hibernate主键生成策略

1、native :主键自增长,更具数据库自动匹配
2、uuid: 使用UUID作为主键
3、increment:用于long、short或int,自增长,每次增量为1
4、identity: 采用数据库本身提供的主键自增策略,不能用于oracle数据库
5、sequence:序列增长,只能用到oracle数据库中

CRUD

save增加方法

	SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
	Session session = sessionFactory.openSession();		
	Transaction tx = session.beginTransaction();
	User user = new User();
	user.setName("lamose").setAge(22).setAddress("China");
	session.save(user);
	tx.commit();
	session.close();
	sessionFactory.close();

get查询方法

	SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
	Session session = sessionFactory.openSession();
	Transaction tx = session.beginTransaction();
	User user = session.get(User.class, 3);
	System.out.println(user);
	tx.commit();
	session.close();
	sessionFactory.close();

update修改方法

	SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
	Session session = sessionFactory.openSession();
	Transaction tx = session.beginTransaction();
	User user = session.get(User.class, 3);
	user.setName("Tory").setAge(22).setAddress("DDY");
	session.update(user);
	tx.commit();
	session.close();
	sessionFactory.close();

delete删除方法

	SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
	Session session = sessionFactory.openSession();
	Transaction tx = session.beginTransaction();
	User user = session.get(User.class, 3);
	session.delete(user);
	tx.commit();
	session.close();
	sessionFactory.close();

实体类的三种状态

1、瞬时态:对象中没有id值,对象与session没有关系,多为save操作

	User user = new User();
	user.setName("lamose").setAge(22).setAddress("China");

2、持久态:对象有id值,对象与session有关联,多为get

	User user = session.get(User.class, 3);

3、托管态:对象里有id值,对象与session没有关系

	User user = new User();
	user.setId(3);
	session.delete(user);

Hibernate缓存

什么是缓存

1、数据存到数据库中,数据库本身就是文件系统。
2、用流方式操作文件效率很低
3、把数据存放到内存中,不使用流方式,可以直接读取内存数据
4、从内存中读取数据,效率高

Hibernate一级缓存

1、hibernate默认开启一级缓存
2、hibernate的一级缓存使用范围是session,从session创建到session关闭
3、hibernate的一级缓存中,存储数据必须是持久态数据

Hibernate二级缓存

1、默认关闭
2、目前已经不使用了,由redis来替代
3、使用范围为SessionFactory范围

Hibernate一级缓存执行过程

在这里插入图片描述

hibernate一级缓存特性

持久态会自动更新数据库

public void testGet() {
	SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
	Session session = sessionFactory.openSession();
	Transaction tx = session.beginTransaction();
	User user = session.get(User.class, 4);
	System.out.println(user);
	user.setAge(22).setName("LLL").setAddress("as");
	User user2 = session.get(User.class, 4);
	System.out.println(user2);
	tx.commit();
	session.close();
	sessionFactory.close();
}

在这里插入图片描述

Hibernate事务操作

推荐使用异常捕获结构来写事务

public void guTransaction() {
	SessionFactory sessionFactory = null;
	Session session = null;
	Transaction tx = null;
	try {
		sessionFactory=HibernateUtil.getSessionFactory();
		session = sessionFactory.openSession();
		tx = session.beginTransaction();
		// CRUD操作
		tx.commit();
	} catch (Exception e) {
		tx.rollback();
	} finally {
		session.close();
		sessionFactory.close();
	}
}

Hibernate绑定

1、在hibernat.cfg.xml中配置本地线程绑定session

	<!-- 配置本地线程绑定session -->
	<property name="hibernate.current_session_context_class">thread</property>		

2、在HibernateUtils中提供返回本地线程对象的session方法

	public static Session getSessionObject() {
		return sessionFactory.getCurrentSession();
	}	

3、调用方法,利用本地线程绑定的session后,不需要手动关闭

	public void testTx() {
		Session session = null;
		Transaction tx = null;
		try {
			session = HibernateUtil.getSessionObject();
			tx = session.beginTransaction();
			//CRUD
			tx.commit();
		} catch (Exception e) {
			tx.rollback();
		} finally {			
		}
	}

hibernate其他API

query对象

	Query createQuery = session.createQuery("from User");
	List<User> list = createQuery.list();
	for (User user : list) {
		System.out.println(user);
	}

criteria对象

	Criteria createCriteria = session.createCriteria(User.class);
	List<User> list = createCriteria.list();
	for (User user : list) {
		System.out.println(user);
	}

sqlquery对象

	SQLQuery sqlQuery = session.createSQLQuery("select * from t_user");
	List<Object[]> list = sqlQuery.list();
	for (Object[] objects : list) {
		System.out.println(Arrays.toString(objects));
	}

Hibernate表关系

一对多

Set标签:

name属性:本实体中,对方实体的名称
table属性:数据库表
cascade属性: save-update 级联保存更新,delete 级联删除
inverse属性:双向维护,默认false不放弃双向维护,建议设置为true

Key标签:

column属性:外键名称

one-to-many标签:

class属性:实体的全路径名
column属性:外键名称

一对多映射配置

一:

在这里插入图片描述
在这里插入图片描述

多:

在这里插入图片描述
在这里插入图片描述
创建核心配置文件,把一对多关系配置到核心配置文件中

<mapping resource="第一个hbm.xml路径"/>
<mapping resource="第二个hbm.xml路径"/>

一对多级联操作

级联保存

1、在一的一方的Set标签中,配置cascade=“save-update”
2、在一的一方创建两个对应对象
3、将多的对象放到一的里面
4、最终只需要保存一的一方,就可以实现级联保存

public void testAdd() {
	SessionFactory sessionFactory = null;
	Session session = null;
	Transaction tx = null;
	try {
		sessionFactory = HibernateUtil.getSessionFactory();
		session = sessionFactory.openSession();
		tx = session.beginTransaction();
		User user1 = new User();
		User user2 = new User();
		User user3 = new User();
		user1.setName("lamose1").setAge(11).setAddress("USA1");
		user2.setName("lamose2").setAge(12).setAddress("USA2");
		user3.setName("lamose3").setAge(13).setAddress("USA3");
		Dept dept = new Dept();
		dept.setDname("开发部门");
		dept.getUserList().add(user1);
		dept.getUserList().add(user2);
		dept.getUserList().add(user3);
		session.save(dept);
		tx.commit();
	} catch (Exception e) {
		tx.rollback();
		e.printStackTrace();
	} finally {
		session.close();
		sessionFactory.close();
	}
}

dept.hbm.xml文件内容

<hibernate-mapping>
	<class name="lamose.entity.Dept" table="t_dept">
		<id name="deptno" column="deptno">
			<generator class="native"></generator>
		</id>
		<property name="dname" column="dname"></property>
		<set name="userList" cascade="save-update,delete" >
			<key column="did"></key>
			<one-to-many class="lamose.entity.User" />
		</set>
	</class>
</hibernate-mapping>

user.hbm.xml文件内容

<hibernate-mapping>
	<class name="lamose.entity.User" table="t_user">
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		<property name="name" column="name"></property>
		<property name="age" column="age"></property>
		<property name="address" column="address"></property>
		<many-to-one name="dept" class="lamose.entity.Dept" column="did"></many-to-one>
	</class>
</hibernate-mapping>

hibernate.cfg.xml文件内容

	<mapping resource="User.hbm.xml"/>
	<mapping resource="Dept.hbm.xml"/>
级联删除

1、在一的一方的Set标签中,配置cascade=“save-update,delete”
2、根据id查询一的一方的对象
3、删除一的一方的对象

inverse属性

在更新外键时,根据hibernate会双向维护外键的特性,会出现多次更新外键,这个操作我们不需要,可以在一的一方的Set标签上添加inverse属性
inverse默认为false:表示不放弃维护,改为true即可

多对多

多对多映射配置

1、在实体类中,添加Set集合,创建对方的对象
2、两个hbm.xml都是用Set标签配置
3、生成两个实体类的Get和Set方法

Hibernate查询方式

对象导航查询

根据ID查询某条数据,根据里面的外键,查询其关联数据

需求:查询部门编号为2的所有员工

public static void main(String[] args) {
	SessionFactory sessionFactory = null;
	Session session = null;
	Transaction tx = null;
	try {
		sessionFactory = HibernateUtil.getSessionFactory();
		session = sessionFactory.openSession();
		tx = session.beginTransaction();
		Dept dept = session.get(Dept.class, 2);
		System.out.println(dept.getUserList().size());
		tx.commit();
	} catch (Exception e) {
		tx.rollback();
		e.printStackTrace();
	} finally {
		session.close();
		sessionFactory.close();
	}
}

OID查询

根据ID查询某一条查询

	Dept dept = session.get(Dept.class, 2);

HQL查询

根据Query对象来查询

1、创建Query对象session.createQuery(“from User”);
2、调用Query对象的list方法,返回一个List对象
session.createQuery(String arg0); arg0为from 实体名

条件查询

1、创建Query对象session.createQuery(" ");
2、使用占位符来添加条件
3、调用setParameter方法
----- query.setParameter(int position, Object val);
需求:查询出name为lamose1,且age大于10的user

public void testSelect2() {
	SessionFactory sessionFactory = null;
	Session session = null;
	Transaction tx = null;
	try {
		sessionFactory = HibernateUtil.getSessionFactory();
		session = sessionFactory.openSession();
		tx = session.beginTransaction();
		Query query = session.createQuery("from User u where u.name = ? and u.age > ? ");
		query.setParameter(0 , "lamose1");
		query.setParameter(1, 10);
		List list = query.list();
		System.out.println(list.size());
		tx.commit();
	} catch (Exception e) {
		tx.rollback();
		e.printStackTrace();
	} finally {
		session.close();
		sessionFactory.close();
	}
}

排序查询

普通sql实现

SELECT * FROM T_USER ORDER BY  ID  [DESC]

HQL排序查询

Query query = session.createQuery("from User u order by id desc");

分页查询

普通sql实现

SELECT * FROM T_USER LIMIT 0,5 ;

HQL分页查询
setFirstResult:开始位置
setMaxResults:显示数

public void testSelectLimit() {
	SessionFactory sessionFactory = null;
	Session session = null;
	Transaction tx = null;
	try {
		sessionFactory = HibernateUtil.getSessionFactory();
		session = sessionFactory.openSession();
		tx = session.beginTransaction();
		Query query = session.createQuery("from User");
		//开始位置
		query.setFirstResult(0);
		//每页记录数
		query.setMaxResults(3);
		List list = query.list();
		tx.commit();
	} catch (Exception e) {
		tx.rollback();
		e.printStackTrace();
	} finally {
		session.close();
		sessionFactory.close();
	}
}

HQL投影查询

查询固定字段的值

public void testSelect3() {
	SessionFactory sessionFactory = null;
	Session session = null;
	Transaction tx = null;
	try {
		sessionFactory = HibernateUtil.getSessionFactory();
		session = sessionFactory.openSession();
		tx = session.beginTransaction();
		Query query = session.createQuery("select name from User");
		List<Object> list = query.list();
		for (Object object : list) {
			System.out.println(object.toString());
		}
		tx.commit();
	} catch (Exception e) {
		tx.rollback();
		e.printStackTrace();
	} finally {
		session.close();
		sessionFactory.close();
	}
}

聚合函数

普通sql
聚合函数:count, max, avg, min , sum ,

SELECT 聚合函数 FROM 表名

HQL聚合函数的使用

SELECT 聚合函数 FROM 实体名

	//返回一个Object对象
	Object obj = query.uniqueResult();
	//统计个数时,object不能直接转成int类型,先转换为Long类型

QBC查询

根据criteria对象来查询
调用criteria对象的方法

QBC查询全部

criteria的list()方法

public void testSelect3() {
	SessionFactory sessionFactory = null;
	Session session = null;
	Transaction tx = null;
	try {
		sessionFactory = HibernateUtil.getSessionFactory();
		session = sessionFactory.openSession();
		tx = session.beginTransaction();
		Criteria criteria = session.createCriteria(User.class);
		List<User> list = criteria.list();
		System.out.println(list.size());
		tx.commit();
	} catch (Exception e) {
		tx.rollback();
		e.printStackTrace();
	} finally {
		session.close();
		sessionFactory.close();
	}
	}

QBC条件查询

使用Criteria对象里面的方法设置条件
1、使用add方法,表示设置条件值
2、在add方法里面,使用Restrictions类实现条件设置

public void testSelect4() {
	SessionFactory sessionFactory = null;
	Session session = null;
	Transaction tx = null;
	try {
		sessionFactory = HibernateUtil.getSessionFactory();
		session = sessionFactory.openSession();
		tx = session.beginTransaction();
		Criteria criteria = session.createCriteria(User.class);
		criteria.add(Restrictions.eq("name", "lamose1"));
		criteria.add(Restrictions.eq("address", "USA1"));
		List list = criteria.list();
		System.out.println(list.size());
		tx.commit();
	} catch (Exception e) {
		tx.rollback();
		e.printStackTrace();
	} finally {
		session.close();
		sessionFactory.close();
	}
}

在这里插入图片描述

QBC排序和分页

criteria.addOrder(Order.desc(" 实体属性名")); //降序
criteria.addOrder(Order.asc(" 实体属性名")); //升序

criteria.setFirstResult( int arg0); //开始位置
criteria.setMaxResults( int arg0); //每页记录数

QBC统计和离线查询

统计查询

1、创建Criteria对象
2、设置操作:criteria.setProjection(Projections.rowCount);
3、得到结果: Object obj = criteria.uniqueResult();

离线查询

1、不需要通过Session对象来创建
2、DetachedCriteria detachedCriteria = DetachedCriteria .forClass(User.class);
3、执行时使用Session对象:Criteria criteria = detachedCriteria.getExecutableCriteria(session);

	DetachedCriteria detachedCriteria = DetachedCriteria.forClass(User.class);
	Criteria criteria = detachedCriteria.getExecutableCriteria(session);
	List list = criteria.list();
	System.out.println(list.size());

HQL多表查询

内连接(返回list部分是 数组)

1、创建Query对象

	Query query = session.createQuery("from Dept u inner join u.userList ");
	List list = query.list();
	System.out.println(list.size());

迫切内连接(返回list部分是 对象)

	Query query = session.createQuery("from Dept u inner join fetch u.userList ");
	List list = query.list();
	System.out.println(list.size());

左(右)外连接

	Query query = session.createQuery("from Dept u left(right) outer join u.userList ");
	List list = query.list();
	System.out.println(list.size());

左外迫切连接

没有右外迫切连接

	Query query = session.createQuery("from Dept u left outer join fetch u.userList ");
	List list = query.list();
	System.out.println(list.size());

Hibernate检索策略

立即查询

根据id查询,调用get方法,一调用get方法,立即发送语句到数据库

延迟查询

根据id查询,还有load方法,不会马上发送语句到数据库,只有得到对象里面的值(调用get方法,调用getId除外)时,才会发送到数据库

	User user = session.load(User.class, 7);
	//不会向数据库发送语句
	user.getId();
	//回向数据发送语句
	user.getName();

类级别延迟

例如上方操作一个User类,就是类级别延迟

关联级别延迟

默认:获取通过关联外键的实体时,不调用关联实体的方法时,不会发送语句
修改:
在Set标签上使用属性
1、fetch:默认值为select
2、lazy:默认值true,延迟是否开

  1. true开启
  2. false不开启,效率低
  3. extra及其懒惰,效率更高,要什么就发什么

批量抓取

在需要通过关联关系多次查询数据库时,可以使用批量抓取来提高效率,减少语句的发送
在Set标签中配置,batch-size=" "
batch-size的属性值为数字,数字越大,性能越高

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值