Hibernate——查询详解、连接池、逆向工程

一、查询详解

参考:https://mp.weixin.qq.com/s/8roKUxjEQOOcK38dRVq_eQ

1.1 主键查询

作用:通过主键来查询数据库的记录,从而返回一个JavaBean对象。

1.1.1 get()立即查询

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

1.1.2 load()懒加载查询

User user = (User)session.load(User.class,2);

1.1.3 对象导航查询

需求:查询部门信息时,直接可以获取到雇员信息,不需要二次查询。

SQL查询时:若想要得到当前对象与另一对象的关联关系时,就必须用多表查询来得到数据。
Hibernate提供了对象导航查询:可以使用主键查询完之后,得到的对象,直接使用对象得到集合…就可以得到对应的数据了。

// 对象导航查询
Dept dept =  (Dept) session.get(Dept.class, 12);
System.out.println(dept.getDeptName());

//这里就可以得到部门对应的所有员工
System.out.println(dept.getEmps());

1.2 HQL查询

HQL:hibernate query language。hibernate提供的面向对象的查询语言。
——查询的是对象以及对象的属性。
——因此区分大小写!

1.2.1 查询全部列

//方式一:直接写对象
String hql1 = "from Dept";
//方式二:可以为对象取别名
String hql2 = "select d from Dept d";
// 注意:HQL不支持*号。
// String hql3 = "select * from Dept d";
Query q = session.createQuery(hql1);
Query q = session.createQuery(hql2);

1.2.2 查询指定的列

使用HQL查询指定的列,返回的是对象数组Object[]。
缺点:不易操作。

//只查询name和eatBanana列
String hql = "select m.name,m.eatBanana from Monkey m";
Query q = session.createQuery(hql);

优化:封装对象。Hibernate还提供了将对象数组封装成对象的功能

// JavaBean要有对应的构造函数
String hql = "select new Monkey(m.name,m.eatBanana) from Monkey m";
Query q = session.createQuery(hql);

1.2.3 条件查询

占位符——?

String hql = "from Monkey m where m.name = ?";
Query query = session.createQuery(hql);
//HQL是从0开始的
query.setParameter(0, "大猴子");

命名参数——:命名

String hql = "from Monkey m where m.name = :monkeyName";
Query query = session.createQuery(hql);
query.setParameter("monkeyName", "大猴子");

范围查询——between and

String hql = "from Dept d where deptId between ? and ?";
Query query = session.createQuery(hql);
query.setParameter(0, 1);
query.setParameter(1, 20);

模糊查询——Like

String hql = "from Dept d where deptName like ?";
Query query = session.createQuery(hql);
// 注意:%号要写在参数上,不能写带SQL上!
query..setString(0, "%部%");

1.2.4 聚合函数统计

HQL提供了uniqueResult()这么一个方法,返回只有一条记录的数据。

String hql = "select COUNT(*) from Monkey";
Query query = session.createQuery(hql);
Object o = query.uniqueResult();
System.out.println(o);

1.2.5 分组查询

String hql = "select e.dept, count(*) from Employee e group by e.dept";
Query query = session.createQuery(hql);

1.2.6 连接查询

种类:
——内连接【等值连接】
——左外连接
——有外链接
注意:连接查询返回的也是对象数组!

// 1) 内连接   【映射已经配置好了关系,关联的时候,直接写对象的属性即可】
String hql1 = "from Dept d inner join d.emps";
// 2) 左外连接
String hql2 = "from Dept d left join d.emps";
// 3) 右外连接
String hql3 = "from Employee e right join e.dept";

Query query = session.createQuery(hql);

优化:迫切连接。
目的:使在返回的时候是一个对象、而不是对象数组!

// 1) 迫切内连接    【使用fetch, 会把右表的数据,填充到左表对象中!】
String hql1 = "from Dept d inner join fetch d.emps";
// 2) 迫切左外连接
String hql2 = "from Dept d left join fetch d.emps";
// 3) 迫切右外连接
String hql3 = "from Employee e right join fetch e.dept";

Query query = session.createQuery(hql);

1.2.7 命名查询

查询语句放在配置文件中。
含义:
1、在具体的映射配置文件中存放一些常用的语句,并命名。
2、在程序中,可以获取配置文件配置的语句。

<!-- 存放sql语句,如果有<>这样的字符数据,需要使用CDATA转义! -->
<query name="getAllDept">
	<![CDATA[ from Dept d where deptId < ? ]]>
</query>
String hql = "getAllDept";
Query query = session.createQuery(hql);
query.setParameter(0, 10);

1.3 QBC查询

QBC查询: query by criteria 。 完全面向对象的查询。
Criteria使用的是add()来添加条件。条件又使用一个Restrictions类来封装。

// 创建Criteria对象
Criteria criteria = session.createCriteria(User.class);
// 添加条件。
criteria.add(Restrictions.eq("id",1));
// 查询全部数据
List<User> list = criteria.list();

Criteria查询就使用不了分组、连接查询了。

1.4 本地SQL查询

提出问题:当表的结构十分复杂时,若使用关联映射,则配置文件是十分臃肿的。因此,并不是所有数据表都使用映射的方式来创建。
解决问题:用SQLQuery来维护数据。
注意:
1、SQLQuery是不能跨数据库的,因为Hibernate在配置的时候就指定了数据库的“方言”。

SQLQuery sqlQuery = session.createSQLQuery("SELECT * FROM monkey_ limit 0,3");
System.out.println(sqlQuery.list());

2、返回的也是对象数组。
3、Hibernate也支持在SQLQuery中对数据进行对象封装。只要添加类型就行了。

SQLQuery sqlQuery = session.createSQLQuery("SELECT * FROM monkey_ limit 0,3").addEntity(Monkey.class);
System.out.println(sqlQuery.list());

1.5 分页查询

1.5.1 传统方式

步骤:
1、得到数据库表中的总记录数。
2、查询起始位置到末尾位数的数据

1.5.2 Hibernate方式

Query query = session.createQuery("from Monkey");
// 得到滚动结果集
ScrollableResults scroll = query.scroll();
//滚动到最后一行
scroll.last();
int totalSize = scroll.getRowNumber() + 1; // 总记录数。
/*
 * String hql = "SELECT COUNT(*) FROM Monkey";
 * Long totalSize = (Long) query.uniqueResult();
 */
//设置分页位置
query.setFirstResult(0);  // 起始位置。
query.setMaxResults(3); // 查询结果最大记录数

System.out.println(query.list());

二、Hibernate连接池

Hibernate自带了连接池,该连接池比较简单。而Hibernate又对C3P0这个连接池支持,因此常更换Hibernate连接池为C3P0。

2.1 查看Hibernate自带的连接池

可以通过Hibernate.properties文件中查看Hibernate默认配置的连接池。
hibernate.properties的配置文件可以在\project\etc找到。
Hibernate的自带连接池啥都没有,就一个连接数量为1。

2.2 查看Hibernate对C3P0的支持

#hibernate.c3p0.max_size 2                最大连接数
#hibernate.c3p0.min_size 2                最小连接数
#hibernate.c3p0.timeout 5000           超时时间
#hibernate.c3p0.max_statements 100     最大执行的命令的个数
#hibernate.c3p0.idle_test_period 3000    空闲测试时间
#hibernate.c3p0.acquire_increment 2     连接不够用的时候, 每次增加的连接数
#hibernate.c3p0.validate false

2.3 修改Hibernate连接池

在hibernate.cfg.xml中配置C3p0,让C30P0作为Hibernate的数据库连接池。
查找Hibernate支持的连接池组件有什么:
在这里插入图片描述
在hibernate.cfg.xml中配置对应的类就和相关配置。

 <!-- 【连接池配置】 -->
<!-- 配置连接驱动管理类 -->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<!-- 配置连接池参数信息 -->
<property name="hibernate.c3p0.min_size">2</property>
<property name="hibernate.c3p0.max_size">4</property>
<property name="hibernate.c3p0.timeout">5000</property>
<property name="hibernate.c3p0.max_statements">10</property>
<property name="hibernate.c3p0.idle_test_period">30000</property>
<property name="hibernate.c3p0.acquire_increment">2</property>

三、线程Session使用

创建Session方法含义
openSession()每次都会创建新的Session
getCurrentSession()获取当前线程的Session,如果没有则创建。

一般地,我们使用线程Session比较多,需要在配置文件中配置。

 <!--配置线程Session-->
<property name="hibernate.current_session_context_class">thread</property>
//openSession:  创建Session, 每次都会创建一个新的session
public void testSession1() throws Exception {	
	Session session1 = sf.openSession();
	Session session2 = sf.openSession();
	System.out.println(session1 == session2);
	session1.close();
	session2.close();
}
// getCurrentSession 创建或者获取session。线程的方式创建session 
public void testSession2() throws Exception {
	// 一定要配置:<property 	name="hibernate.current_session_context_class">thread</property>
	Session session3 = sf.getCurrentSession();// 创建session,绑定到线程
	Session session4 = sf.getCurrentSession();// 从当前访问线程获取session
	System.out.println(session3 == session4);

	// 关闭 【以线程方式创建的session,可以不用关闭; 线程结束session自动关闭】
	//session3.close();
	//session4.close(); 报错,因为同一个session已经关闭了!
}

四、逆向工程

提出问题:由于我们每次编写Hibernate的时候都需要写实体,写映射文件。而且Hibernate的映射文件也容易出错。而逆向工程可以帮我们自动生成实体和映射文件,这样就非常方便了。

4.1 使用PowerDesigner

在设计数据库表时,我们使用PowerDesigner来生成概念模型\物理模。
设计一个人员组织架构:有机构、部门、员工、领导、角色、权限。
1、一个机构有多个部门
2、一个部门有多个员工
3、领导可以管理多个部门,同时领导他自己也是员工
4、一个员工可以有多个角色
5、一个角色可以分配给多个人
6、人员角色分配后可以设置是否有效,分配时间等
7、一个角色有多个权限

4.2 概念模型

在PowerDesigner中,箭头指向的方向永远是“一”的一方。
在这里插入图片描述

4.3 生成物理模型


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

4.4 生成sql语句

我们可以单个生成,一个一个复制。
在这里插入图片描述
也可以把整个物理模型的sql语句一起生成。

在这里插入图片描述


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值