一、Hibernate中的关联关系

1.1、单向一对多关联关系

按照以下步骤配置hibernate中持久化类的一对多对象关联:

(1).持久化类添加关联类的相关属性及getter/setter方法。

(2).映射文件中建立该属性和数据库表字段的映射信息。

比如班级对学生是一对多的关系,班级类Grade类和Grade.hbm.xml文件如下:

package com.pb.hibernate.po;

import java.util.HashSet;

import java.util.Set;

public class Grade {

private int gid;

private String gname;

private String gdesc;

private Set students=new HashSet();

public Set getStudents() {

return students;

}

public void setStudents(Set students) {

this.students = students;

}

public int getGid() {

return gid;

}

public void setGid(int gid) {

this.gid = gid;

}

public String getGname() {

return gname;

}

public void setGname(String gname) {

this.gname = gname;

}

public String getGdesc() {

return gdesc;

}

public void setGdesc(String gdesc) {

this.gdesc = gdesc;

}

public Grade() {

super();

}

public Grade(int gid, String gname, String gdesc, Set students) {

super();

this.gid = gid;

this.gname = gname;

this.gdesc = gdesc;

this.students = students;

}

}

Grade.hbm.xml文件:

/p>

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

使用元素和元素配置一对多关系,元素常用属性如下:

1.name:关联类属性的名称,是必须填写,没有默认值。

2.table:关联类的目标数据库表,可以不关联数据表,没有默认值。

3.lazy:指定关联对象延迟加载策略,默认为true.

4.fetch:设置抓取数据的策略,默认为select.

5.inverse:描述对象之间关联关系的维护方式,默认为false.

1.2、单向多对一关联关系

多对一关联关系和配置一对多关联关系步骤一样,不同的是在配置文件中使用元素配置多对一关联。

package com.pb.hibernate.po;

import java.util.HashSet;

import java.util.Set;

public class Student {

private int sid;

private String sname;

private String sex;

private Grade grade;// 定义班级属性

private Paper paper;

private Set courses=new HashSet();

public Set getCourses() {

return courses;

}

public void setCourses(Set courses) {

this.courses = courses;

}

public int getSid() {

return sid;

}

public void setSid(int sid) {

this.sid = sid;

}

public String getSname() {

return sname;

}

public void setSname(String sname) {

this.sname = sname;

}

public String getSex() {

return sex;

}

public void setSex(String sex) {

this.sex = sex;

}

public Grade getGrade() {

return grade;

}

public void setGrade(Grade grade) {

this.grade = grade;

}

public Paper getPaper() {

return paper;

}

public void setPaper(Paper paper) {

this.paper = paper;

}

public Student() {

super();

}

}

在Student.hbm.xml文件中配置实体与表的关联关系:

/p>

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

1.3、双向一对多关联关系:

单向一对多和单向多对一可以分别配置使用,如果同时配置了两者,就成了双向一对多关联关系,其实在上面就完成了双向一对多关联关系。

1.4、一对一关联关系

数据库表的一对一关联关系可以通过主键关联以及外键关联实现,常使用外键进行关联。

使用学生表Student和学生证表paper是一对一关联,xml配置文件如下:

Student表的hibernate.hbm.xml文件在上面已经描述不再赘述,下面是学生证表对应的xml配置文件:

/p>

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

需要注意的是在Student.hbm.xml中,并不需要指定属性所对应的数据表的列,而是通过paperty-ref指向paper类中的关联对象属性student,在paper.hbm.xml中添加了属性upique="true"的作用等同与。

1.5、多对多关联关系

Hibernate中多对多对象关联的实现方式有一下两种:

1.不创建中间表的持久化类,只创建两端数据库表的持久化类,在映射文件中使用标签设置映射。

2.创建中间表,两端数据表的持久化类,针对中间表的持久化类分别和两端的数据库表的持久化类创建一对多关联。

数据库中多对多关联关系是通过中间表实现的,通过中间表,将两个表之间的多对多关联关系分别转换为它们和中间表之间的一对多关联关系。

使用学生Student对课程Course之间的多对多关联关系为例设置多对多关联关系,其中Student类的xml文件的配置已经在上面描述,下面是Course类的xml文件配置信息。

/p>

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

在配置Student对象和Course对象时候我们注意到有两个属性:cascade(级联)和inverse(反转)

1.cascade属性:级联操作是指当主控方执行某项操作时,是否要对被关联放也执行相同的操作,常用的有,,,使用cascade属性的常用值如下:

(1).all:对所有操作进行级联操作。

(2).save-update:执行保存和更新操作时进行级联操作。

(3).delete:执行删除操作时进行级联操作。

(4).none:对所有操作不进行级联操作。

2.inverse属性:是对象之间关联关系的维护方式,它可以将维护关联关系的任务反转,由对方完成,inverse只存在与集合标记的元素中,inverse为true时,数量为一的一方反转关联关系维护给多的一方,inverse为false时为主动方,有主动方负责维护关联关系。

二、Hibernate检索方式

Hibernate中提供了一下几种在数据库中检索对象的方式:

(1).导航对象图检索方式:根据已经加载的对象,导航到其他对象,如关联对象的查询。

(2).OID检索方式:按照对象的OID来检索对象。

(3).HQL检索方式:使用专门的HQL查询接口和面向对象的HQL查询语言。

(4).QBC(Query By Criteria)检索方式:QBC提供的API来检索对象,这种API封装了基于字符串形式的查询语言,提供了更加面向对象的查询接口。

(5).本地SQL检索方式:这也是官方推荐的标准查询方式。

2.1、HQL查询

HQL(Hibernate Query Language)是Hibernate提供的一种面向对象的查询语言,HQL提供了了更加丰富灵活并且强大的功能。

>使用HQL可以避免使用JDBC查询的一些弊端,不需要再编写复杂的sql,将针对实体类及属性进行查询。

>查询结果直接放在List中的对象中,不需要,再次封装。

>独立于数据库,对不同的数据库根据Hibernate dialect属性自动生成不同的sql语句。

Query接口是HQL查询接口,提供了各种查询功能,它相当于JDBC的Statement和PreparedStatement,通过Session的createQuery创建其对象。理解其list()与iterate()方法的查询机制,将有助于查询性能的优化。

>list()方法返回List对象,iterate()方法直接返回Iterator对象。

>list()方法将不会在缓存中读取数据,它总是一次性地从数据库中直接查询所有符合条件的数据,同时将获取的数据写入缓存。

>iterate()方法是获取符合条件的数据的id后,需要时根据id在缓存中寻找符合条件的数据,若缓存中没有符合条件的数据,再到数据库中查询。

HibernateUtil工具类:

package com.pb.hibernate.util;

import org.hibernate.HibernateException;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

public class HibernateUtil {

/**

* 初始化一个ThreadLocal对象,ThreadLocal对象有get(),set()方法;

*/

private static final ThreadLocal sessionTL=new ThreadLocal();

private static Configuration conf;

private static SessionFactory sf;

//静态代码块,只执行一次

static{

try {

//解析配置文件

conf=new Configuration().configure();

//创建sesssion工厂

sf=conf.buildSessionFactory();

} catch (Exception e) {

e.printStackTrace();

}

}

/**

* 得到session对象,同时设置session对象到ThreadLocal对象

* 确保一个线程用一个session对象,而不是多个线程共享一个session对象

* @return 从ThradLocal对象中得到的session对象

*/

public static Session getCurrentSession(){

//多线程不公用session

Session session=sessionTL.get();

if (session==null) {

//得到session对象

session=sf.openSession();

//将session对象保存到threadLocal对象中

sessionTL.set(session);

}

return session;

}

/**

* 关闭session ,同时从ThreadLocal对象中清除缓存

*/

public static void closeSession(){

Session session =sessionTL.get();

sessionTL.set(null);//先清空threadLocal

session.close();

}

}

DAO层使用hql查询:

/**

* 通过hql语句的query.list()方法得到所有的像的集合

* @return

*/

public List getAll(){

//1.得到session

Session session=HibernateUtil.getCurrentSession();

//2.hql语句

String hql="from Dept";

//得到query对象

Query query=session.createQuery(hql);

List list=query.list();

return list;

}

2.2、属性查询

属性查询只查找持久化类的部分属性而不是全部属性,通过属性查询有两种方式:

(1).通过直接指定属性进行属性查询,例如:

/**

* @param deptName

* @param location

* @return

*/

public List getDeptByNameAndLoc(String deptName,String location){

Session session=HibernateUtil.getCurrentSession();

String hql="select deptName,location from Dept";

Query query=session.createQuery(hql);

List list2=query.list();

for (Object[] objects : list2) {

System.out.println(objects[0]+""+objects[1]);

}

return null;

}

(2).通过构造方法进行属性查询,使用这种方法需要持久化类中添加相应的构造方法。

/**

* @param deptName

* @param location

* @return

*/

public List getDeptByNameAndLoc(String deptName,String location){

Session session=HibernateUtil.getCurrentSession();

String hql="select new Dept( deptName,location) from Dept";

Query query=session.createQuery(hql);

List list2=query.list();

for (Object[] objects : list2) {

System.out.println(objects[0]+""+objects[1]);

}

return null;

}

2.3、参数绑定

(1).使用"?"占位符。

public List getDeptByDeptName(String deptName){

Session session=HibernateUtil.getCurrentSession();

String hql="from Dept where deptName like ? ";

Query query=session.createQuery(hql);

//setXxx ;Xxx:数据类型

query.setString(0,"%"+deptName+"%");

List list=query.list();

return list;

}

(2).使用命名参数。

//参数名称绑定参数

public List get(){

Session session=HibernateUtil.getCurrentSession();

//命名参数

String hql="from Dept where deptName=:deptName";

Query query=session.createQuery(hql);

/**

* 实体类以及对应的映射文件,自动生成

* 方向工程

*/

query.setString("deptName", "deptName");

// query.setParameter("deptName","deptName");

List list=query.list();

for (Dept dept : list) {

System.out.println(dept.getDeptName());

}

return null;

}

2.4、Hibernate分页

/**

* 通过hql语句的query.list()方法得到所有的像的集合

* 分页查询

* @return

*/

public List getAll(int pageIndex){

//1.得到session

Session session=HibernateUtil.getCurrentSession();

//2.hql语句

String hql="from Dept";

//得到query对象

Query query=session.createQuery(hql);

/**

* 每页显示2条数据

* 显示第五页

*/

query.setMaxResults(3);//pageSize每页显示多少条数据

query.setFirstResult((pageIndex-1)*3);//设置第一个,不包括第一个数据(pageIndex-1)*pageSize

List list=query.list();

return list;

}

/**

* 得到总页数

* @param deptName

* @return

*/

public int getTotalCount(String deptName){

Session session=HibernateUtil.getCurrentSession();

StringBuffer hql=new StringBuffer("select count(*) from Dept where 1=1");

List params=new ArrayList();

if (deptName!=null&&!"".equals(deptName)) {

hql.append(" and deptName like ?");

params.add("%"+deptName+"%");

}

Query query=session.createQuery(hql.toString());

for (int i = 0; i < params.size(); i++) {

query.setParameter(i, params.get(i));//第二个参数放入的是Object类型

}

long count =(Long)query.uniqueResult();

int totalCount=(int)count;

if (totalCount%3==0) {

return totalCount/3;

}else {

return totalCount/3+1;

}

}

2.5、Criteria查询概述

Criteria查询(Query By Criteria, QBC)是与HQL完全不同的一种查询机制。Criteria查询又称对象查询,它采用对象的方式,封装查询条件,并提供了Restriction等类型做辅助,可以使编写查询代码更加方便。

使用Criteria的示例:

/**

* 使用Criteria查询

*/

public Dept getDeptByCriteria(){

try {

Session session=HibernateUtil.getCurrentSession();

Criteria criteria = session.createCriteria(Dept.class);

Dept dept=(Dept) criteria.uniqueResult();

return dept;

} catch (HibernateException e) {

e.printStackTrace();

}

return null;

}

public Dept getDeptByCriteriaUseRestrictions(){

try {

Session session=HibernateUtil.getCurrentSession();

Criteria criteria = session.createCriteria(Dept.class);

criteria.add(Restrictions.eq("deptNo", "101"));// 添加限制条件

//criteria.addOrder(Order.desc("deptNo"));排序

Dept dept=(Dept) criteria.uniqueResult();

return dept;

} catch (HibernateException e) {

e.printStackTrace();

}

return null;

}

在Criteria查询中使用Example示例查询:

在使用Criteria查询时,设定查询条件并非一定使用Restrictions,如果属性条件更多,使用Restrictions也不方便,Criteria允许先创建一个对象模板,以这样一个对象模板作为查询依据,查询出来属性与类似的对象。也就是依照已有的对象,查询与其属性相同或者相似的其他对象,这种查询也称示例查询(Query By Example,QBE)。

public List getDeptByExample(){

List result = null;

try {

Session session=HibernateUtil.getCurrentSession();

Dept dept = new Dept();

dept.setLocation("上海");

Criteria criteria = session.createCriteria(Dept.class);

/**

* Hibernate在自动生成SQL语句时,将自动过滤对象的空属性,

* 根据有非空属性生成查询条件,如果要想更加精准可以设置更多属性值

*/

criteria.add(Example.create(dept));

result = criteria.list();

return result;

} catch (HibernateException e) {

e.printStackTrace();

}

return null;

}

使用Criteria实现统计、分组、分页:

/**

* 使用Criteria查询

*/

public List getDeptByCriteria(){

List result = null;

try {

Session session=HibernateUtil.getCurrentSession();

Criteria criteria = session.createCriteria(Dept.class);

criteria.setProjection(Projections.projectionList()

.add(Projections.groupProperty("deptName")) // 按部门名称分组

.add(Projections.rowCount()) // 统计所有记录数

.add(Projections.avg("deptName"))// 统计平均数

.add(Projections.max("deptNo")));// 求最大

result= criteria.list();

return result;

} catch (HibernateException e) {

e.printStackTrace();

}

return null;

}

//分页

public List getDeptByCriteriaPage(){

List result = null;

try {

Session session=HibernateUtil.getCurrentSession();

Criteria criteria = session.createCriteria(Dept.class);

criteria.setFirstResult(1);

criteria.setMaxResults(3);

result= criteria.list();

return result;

} catch (HibernateException e) {

e.printStackTrace();

}

return null;

}

2.6、命名HQL查询

在Dept.hbm.xml中配置:

/p>

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

seq_dept

from Dept d where d.deptNo=:deptNo

]]>

查询:

public List getDeptByCriteria(){

List result = null;

try {

Session session=HibernateUtil.getCurrentSession();

Query query = session.getNamedQuery("dept");

Dept dept = new Dept();

dept.setDeptNo(101);

query.setProperties(dept);

result= query.list();

return result;

} catch (HibernateException e) {

e.printStackTrace();

}

return null;

}

2.7、DetachedCriteria查询

public List getAllExamByExamId(Integer examId,

String[] classIds) {

DetachedCriteria detachedCriteria = DetachedCriteria

.forClass(getEntityClass());

detachedCriteria.add(Restrictions.eq("exam.id", examId));

detachedCriteria.add(Restrictions.eq("isDelete",

MySchoolConstant.IS_DELETED_NO));

boolean error = false;

Integer[] intClassIds = new Integer[classIds.length];

for (int i = 0; i < classIds.length; i++) {

if (StringUtils.isEmpty(classIds[i])) {

error = true;

break;

}

intClassIds[i] = Integer.valueOf(classIds[i]);

}

if (!error && intClassIds.length > 0) {

detachedCriteria.add(Restrictions.in("classId", intClassIds));

}

return findList(detachedCriteria);

}

2.8、本地sql查询

HQL查询并不能涵盖所有的查询特性,一些复杂的查询还必须借助sql达到期望的目标,也就是本地sql,使用query.createSQLQuery(String sql)方法,同时使用addEntity()方法将别名与实体类关联起来。

public ZAnswer findStudentZAnswerListByParams(Integer recruitId,Integer examId,Integer questionId,Integer userId) {

StringBuffer sql = new StringBuffer();

sql.append(" SELECT * FROM Z_ANSWER t ");

sql.append(" WHERE t.`IS_DELETED` = 0 ");

sql.append(" AND t.`RECRUIT_ID` = :recruitId ");

sql.append(" AND t.`EXAM_ID` = :examId ");

sql.append(" AND t.`TEST_QUESTION_ID` = :questionId ");

sql.append(" AND t.`ANSWER_USER_ID` = :userId ");

sql.append(" ORDER BY t.`IS_CURRENT` DESC,t.`CREATE_TIME` DESC ");

Query query = this.getSession().createSQLQuery(sql.toString()).addEntity(ZAnswer.class);

query.setParameter("recruitId", recruitId);

query.setParameter("examId", examId);

query.setParameter("questionId", questionId);

query.setParameter("userId", userId);

@SuppressWarnings("unchecked")

List result = query.list();

//取得第一条记录

ZAnswer answer = null;

//排除重复

if(result.size() > 0){

answer = (ZAnswer) result.get(0);

for (ZAnswer zAnswer : result) {

if(zAnswer.getId() != answer.getId()){

zAnswer.setIsDelete(1);

this.update(zAnswer);

}

}

}

return answer;

}

2.9、Hibernate调用存储过程

创建两个存储过程,在存储过程中in表示输入,out表示输出。

1.根据id查找某条数据:

CREATE PROCEDURE `findEmpById`(IN id INTEGER(11))

begin

select * from emp where empId=id;

end;

2.根据id查找某个字段并返回

CREATE PROCEDURE `getNameById`(in id integer(11),out eName varchar(50))

begin

select empName into eName from emp where empId=id;

end;

调用第一个存储过程:

package com.test;

import java.sql.CallableStatement;

import java.sql.Connection;

import java.sql.ResultSet;

import java.sql.SQLException;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

public class 调用存储过程 {

/**

* @param args

* @throws SQLException

*/

public static void main(String[] args) throws SQLException {

Configuration cfg = new Configuration().configure();

SessionFactory factory = cfg.buildSessionFactory();

Session session = factory.openSession();

Connection con = session.connection();

String sql = "{call findEmpById(?)}";

CallableStatement cs = con.prepareCall(sql);

cs.setObject(1, 2);

ResultSet rs = cs.executeQuery();

while(rs.next()){

int id = rs.getInt("empId");

String name = rs.getString("empName");

System.out.println(id+"\t"+name);

}

}

}

调用第二个存储过程:

package com.test;

import java.sql.CallableStatement;

import java.sql.Connection;

import java.sql.SQLException;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

public class 调用存储过程1 {

public static void main(String[] args) throws SQLException {

Configuration config = new Configuration().configure();

SessionFactory sessionFactory = config.buildSessionFactory();

Session session = sessionFactory.openSession();

Connection conn = session.connection();

String sql = "{call getNameById(?,?)}";

CallableStatement cs = conn.prepareCall(sql);

cs.setObject(1, 3); //设置输出参数

cs.registerOutParameter(2, java.sql.Types.VARCHAR); //设置第二个参数为输出参数

cs.execute(); //调用存储过程

String name = cs.getString(2);//获取输出参数

System.out.println(name);

}

}

hibernate mysql 关联查询_Hibernate关联映射及高级查询相关推荐

  1. mysql查询显示技巧_MYSQL SQL高级查询技巧

    1.UNION,EXCEPT,INTERSECT运算符 A,UNION 运算符 UNION 运算符通过组合其他两个结果表(例如 TABLE1 和 TABLE2)并消去表中任何重复行而派生出一个结果表. ...

  2. mysql查询高于平均_Mysql之高级查询

    Mysql之高级查询 一.函数&分组查询 1.函数 Mysql已经定义好的,可以实现一定功能的代码块 日期函数.数字函数.字符函数.聚合函数 聚合函数:聚合函数对整体进行运算,通常返回的结果只 ...

  3. Python ORM之SQLAlchemy 数据库连接引擎实现Mysql、PostgreSQL、Oracle连接以及高级查询的相关实例

    1 环境 SQLAlchemy 2.0.7 PyMySQL 1.0.2 Python 3.8.16 2 背景 SQLAlchemy 工具 实现多种数据库连接支持 MetaData.automap_ba ...

  4. mysql数据库高级查询笔记_MySQL数据库基础——高级查询

    MySQL数据库入门--day08 高级查询 一.聚合函数: 在实际开发过程中经常需要对数据进行统计,为此MySQL中提供了一些函数来实现某些功能如下表所示: 聚合函数 1.COUNT()函数: CO ...

  5. php mongo分页查询,PHP操作Mongodb之高级查询篇

    标签: 1.查询时的排序 在关系型数据库的查询中,往往会用到排序.例如时间倒序,点击率升序啦等等.在Mongodb的查询中,也有排序功能的. 语法格式: $db->find()->sort ...

  6. lambdaquerywrapper查询指定字段_MongoDB系列 | 高级查询与索引(四)

    1 . 覆盖索引查询 ​所有的查询字段都是索引的一部分:所有的查询返回字段在同一个索引中. 由于索引存在于 RAM 中,因而从索引中获取数据要比扫描文档更快. 范例: 创建如下 users 集合(使用 ...

  7. hibernate mysql自定义变量_hibernate如何得到mysql的变量

    你这执行的是纯sql,貌似有的hibernate版本不能直接用sql操作mysql数据库,我猜你没在别的方法里用SQLQuery,如果其他地方可以执行那我给你的办法你就不用看了.我当时遇到过hiber ...

  8. hibernate mysql 时间比较_Hibernate中HQL函数汇总及获取当前时间进行比较举例

    在很多时候,我们负责的项目中,在数据访问层(DAO层)通常我们会使用sql语句或者hql语句,而在我们使用hql语句拼接时有时会报错,通常的原因是:我们使用了标准的sql语句,开启的确是hiberna ...

  9. hibernate mysql 设置时区_Hibernate连接MYSQL失败提示时区错误该怎么解决?

    平台: WIN10 X64 专业版. IDEA 2016.1.1. MYSQL 5.7.12 hibernate 4.2.2 具体问题: 用hibernate连接MYSQL数据库的时候提示 ERROR ...

最新文章

  1. iOS 消息推送原理及实现总结
  2. 事务控制语句,begin,rollback,savepoint,隐式提交的SQL语句
  3. python中查看显卡状态
  4. java学习笔记:使用dom4j解析xml
  5. go初学者安装echo框架
  6. docker如何修改挂载路径(挂载目录)?(没弄完,先去弄别的)
  7. 快速排序(quick sort)
  8. pg数据库 设置不区分大小写_pg数据库表名、字段名大小写问题
  9. (51)FPGA面试题-Verilog中function与task之间的区别是什么?
  10. iptables表与链的相关性图
  11. C# 滑块长度确认 Scrollbar滑块长度问题 水平垂直滚动条滑块高度宽度问题
  12. 用户故事与敏捷方法 - 第二章 编写故事
  13. urllib.request.urlopen()出现的程序超时假死问题
  14. [py] 考拉兹猜想
  15. 2、软件造价总结(主要基准数据)
  16. 活着活着,就明白了(精辟)
  17. Quartus的SignalTap的使用
  18. Echarts学习总结(一)-----柱状图
  19. 怎么能把Excel数据导入到这个水经注软件里?
  20. 洛谷P1554 梦中的统计

热门文章

  1. 02-NVIDIA Jetson TX2 通过JetPack 3.1刷机完整版(踩坑版)
  2. C# ASP.NET Forms身份认证
  3. FFmpeg封装格式处理2-解复用例程
  4. JS基础入门篇(四十三)—ES6(二)
  5. linux下tomcat服务器的启动和关闭以及查看实时打印日志
  6. Debian9.1下安装后没有ifconfig命令
  7. 美图HTTPS优化探索与实践
  8. ExtJs6 理解 -- Ext.data.proxy.Proxy
  9. tomcat实现session集群及tomcat+memcached共享session存储(四)
  10. spring InitializingBean接口