hibernate多表关联查询
很多同学在进行编程学习时缺乏系统学习的资料。本页面基于hibernate多表关联查询内容,从基础理论到综合实战,通过实用的知识类文章,标准的编程教程,丰富的视频课程,为您在hibernate多表关联查询相关知识领域提供全面立体的资料补充。同时还包含 h6、hack、hadoop 的知识内容,欢迎查阅!
hibernate多表关联查询相关知识
-
多表查询之多表查询的概述1.1.1 多表查询的分类1.1.1.1 连接查询l 交叉连接:cross joinn 交叉连接:查询到的是两个表的笛卡尔积。n 语法:u select from 表1 cross join 表2;u select from 表1,表2;l 内连接:inner join(inner是可以省略的)n 显示内连接:在SQL中显示的调用inner join关键字u 语法:select from 表1 inner join 表2 on 关联条件;n 隐式内连接:在SQL中没有调用inner join关键字u 语法:select from 表1,表2 where 关联条件;l 外连接:outer join(outer可以省略的)n 左外连接:u 语法:select from 表1 left outer join 表2 on 关联条件;n 右外连接u 语法:select from 表1 right outer join 表2 on 关联条件;1.1.1.2 子查询l 子查询:一个查询语句条件需要依
-
Java面试题:Hibernate的二级缓存与Hibernate多表查询我们来看两个有关Java框架之Hibernate的面试题,这是关于Hibernate的常考知识点。1、请介绍一下Hibernate的二级缓存解题按照以下思路来回答:(1)首先说清楚什么是缓存;(2)再说有了hibernate的Session就是一级缓存,即有了一级缓存,为什么还要有二级缓存;(3)最后再说如何配置Hibernate的二级缓存。缓存就是把以前从数据库中查询出来和使用过的对象保存在内存中(一个数据结构中),这个数据结构通常是或类似Hashmap,当以后要使用某个对象时,先查询缓存中是否有这个对象,如果有则使用缓存中的对象,如果没有则去查询数据库,并将查询出来的对象保存在缓存中,以便下次使用。下面是缓存的伪代码:引出hibernate的第二级缓存,用下面的伪代码分析了Cache的实现原理。Dao{hashmap map =new map();User getUser(integer id){User user = map.get(id)if(user ==null){user = session.
-
Java面试题:Hibernate的二级缓存与Hibernate多表查询我们来看两个有关Java框架之Hibernate的面试题,这是关于Hibernate的常考知识点。1、请介绍一下Hibernate的二级缓存解题按照以下思路来回答:(1)首先说清楚什么是缓存;(2)再说有了hibernate的Session就是一级缓存,即有了一级缓存,为什么还要有二级缓存;(3)最后再说如何配置Hibernate的二级缓存。缓存就是把以前从数据库中查询出来和使用过的对象保存在内存中(一个数据结构中),这个数据结构通常是或类似Hashmap,当以后要使用某个对象时,先查询缓存中是否有这个对象,如果有则使用缓存中的对象,如果没有则去查询数据库,并将查询出来的对象保存在缓存中,以便下次使用。下面是缓存的伪代码:引出hibernate的第二级缓存,用下面的伪代码分析了Cache的实现原理。Dao{hashmap map =new map();User getUser(integer id){User user = map.get(id)if(user ==null){user = session.
-
浅谈mysql中多表不关联查询的实现方法大家在使用MySQL查询时正常是直接一个表的查询,要不然也就是多表的关联查询,使用到了左联结(left join)、右联结(right join)、内联结(inner join)、外联结(outer join)。这种都是两个表之间有一定关联,也就是我们常常说的有一个外键对应关系,可以使用到 a.id = b.aId这种语句去写的关系了。这种是大家常常使用的,可是有时候我们会需要去同时查询两个或者是多个表的时候,这些表又是没有互相关联的,比如要查user表和user_history表中的某一些数据,这个时候就是所谓的不关联查询了。这时候用的是union all语句。比如:?1</pre> <pre class="html" name="code">(select name,sex,age from user where name like '王%' ) union all (select name,sex,age from use
hibernate多表关联查询相关课程
-
揭秘PHP模糊查询技术 在大数据时代,在繁杂的信息中,在PHP的开发过程中,通过什么技术能像“剪枝蔓,立主脑”一样快速准确地查找客户想要的信息?这技术就是PHP模糊查询技术,本课程就从本质上揭密PHP模糊查询技术。
讲师:HappyLiu 初级 24281人正在学习
hibernate多表关联查询相关教程
- 3. 双向一对多关联映射 需求:查询班级时,想知道班上有多少名学生,又应该如何映射?进入班级类,添加如下属性:private Set<Student> students;使用集合属性 students,描述了一个班有多名学生。为什么使用 Set 集合?因为一个班级内不可能出现两个完全相同的学生对象。这还仅仅只是 OOP 层面上的关系,还需要告诉 Hibernate 应该如何填充数据。添加下面代码:private Set<Student> students;@OneToMany(targetEntity=Student.class,mappedBy="classRoom")public Set<Student> getStudents() { return students;}@OneToMany:很直白的说明了一个班级会有多名学生,指引 Hibernate 在填充数据时,要找到所有学生,别遗漏了;属性 mappedBy=“classRoom”: 告诉 Hibernate,班级和学生之间的关系在学生类中已经说的够明白了,应该不需要再废话了吧。OK!把前面的测试实例改为查询班级信息:HibernateTemplate<ClassRoom> hibernateTemplate = new HibernateTemplate<ClassRoom>(); hibernateTemplate.template(new Notify<ClassRoom>() { @Override public ClassRoom action(Session session) { ClassRoom classRoom=(ClassRoom)session.get(ClassRoom.class, new Integer(1)); System.out.println("班级名称:"+classRoom.getClassRoomName());System.out.println("------我是分隔线------------------------"); System.out.println("班级学生人数:"+classRoom.getStudents().size()); return classRoom; } });查看控制台输出结果:Hibernate: select classroom0_.classRoomId as classRoo1_0_0_, classroom0_.classRoomDesc as classRoo2_0_0_, classroom0_.classRoomName as classRoo3_0_0_ from ClassRoom classroom0_ where classroom0_.classRoomId=?班级名称:c1911------我是分隔线------------------------Hibernate: select students0_.classRoomId as classRoo6_0_1_, students0_.stuId as stuId1_1_1_, students0_.stuId as stuId1_1_0_, students0_.classRoomId as classRoo6_1_0_, students0_.stuName as stuName2_1_0_, students0_.stuPassword as stuPassw3_1_0_, students0_.stuPic as stuPic4_1_0_, students0_.stuSex as stuSex5_1_0_ from Student students0_ where students0_.classRoomId=?班级学生人数:2会发现一个很有意思的地方。Hibernate 查询班级时,构建了两条 SQL。先查询班级,当需要学生信息时,才构建查询学生的 SQL。大家应该也猜出来了,当从学生表查询班级表时,Hibernate 采用的是立即策略。当查询从班级表查询到学生表时,Hibernate 采用的是延迟加载策略。采用延迟加载都只有一个目的,需要时加载,提高响应速度。现在,学生类和班级类的映射配置信息,能让 Hibernate 自动从学生表查询到班级表,也能从班级表查询到学生表。这种 2 个实体类中的映射关系就称为双向一对多关联映射。无论是 @ManyToOne 还是 @OneToMany 注解都有 fetch 属性,可以设置的值有 2 个选择:FetchType.EAGERFetchType.LAZY。所以,在双向一对多关联映射可以选择是否启用延迟加载,这和一对一关联映射中是一样的,就不在此重复复述。是否采用延迟加载,由项目逻辑决定。
- 2.2 高级查询 排序查询使用 order API 实现:criteria.addOrder(Order.desc("stuId"));criteria.addOrder(Order.asc("stuName"));一样,可以多字段排序。使用聚合函数:聚合函数的功能封装在 projections API 中:criteria.setProjection(Projections.rowCount());criteria.setProjection(Projections.avg("stuId"));criteria.setProjection(Projections.max("stuId"));criteria.setProjection(Projections.min("stuId"));criteria.setProjection(Projections.sum("stuId"));Criteria 也能实现关联查询:Criteria criteria = session.createCriteria(Student.class);criteria.add(Restrictions.like("stuName", "Hibernate%"));Criteria criteria01 = criteria.createCriteria("classRoom");criteria01.add(Restrictions.like("classRoomName", "c19%"));List<Student> students = criteria.list();可以把一个 Criteria 实例看成对一张表的查询,如果需要关联多张表,则可以通过一个 Criteria 再创建一个 Criteria 对象。Hibernate 为 Criteria 查询提供各种各样的 API,适应于任何查询需求,相比较使用的已经很普遍的 SQL 查询,Criteria 查询充满了鸡肋的味道。但对于动态查询需求,Criteria 查询的优势又很明显。
- 3. 关联映射中的延迟加载 关联多表查询时可选择是否启用延迟加载。PO 之间的映射,意味着 Hibernate 不仅能查询到指定表中数据,还能查询相关联表中的数据。但,有时只需要查询学生基本信息,并不需要地址信息,或者地址信息并不需要马上查询出来,能不能告诉 Hibernate,只查询学生信息,暂且别查询地址信息。同样,有时只需要查询所在地址,并不关心地址对应学生信息。可以启动关联映射中的延迟加载实现上面的需求。学生类中修改代码如下:@OneToOne(targetEntity = Address.class,fetch=FetchType.LAZY)@JoinColumn(name = "addressId")public Address getAddress() { return address;}@OneToOne 注解有 fetch 属性,为枚举类型,其值可选择:FetchType.LAZY;FetchType.EAGER。其作用便是告诉 Hibernate,是否延后或立即查询相关联表中的数据。执行下面测试代码:try { transaction = session.beginTransaction(); Student stu = (Student) session.get(Student.class, new Integer(1)); System.out.println("----------------学生信息---------------"); System.out.println("学生姓名:" + stu.getStuName()); transaction.commit();} catch (Exception e) { transaction.rollback();} finally { session.close();}查看结果:Hibernate: select student0_.stuId as stuId1_1_0_, student0_.addressId as addressI6_1_0_, student0_.stuName as stuName2_1_0_, student0_.stuPassword as stuPassw3_1_0_, student0_.stuPic as stuPic4_1_0_, student0_.stuSex as stuSex5_1_0_ from Student student0_ where student0_.stuId=?----------------学生信息---------------学生姓名:Hibernate老大Hibernate 只构建了一条简单的 Sql 语句, 用于查询学生信息。继续执行下面测试实例:try { transaction = session.beginTransaction(); Student stu = (Student) session.get(Student.class, new Integer(1)); System.out.println("----------------学生信息---------------"); System.out.println("学生姓名:" + stu.getStuName()); System.out.println("-----------------地址信息-----------------"); System.out.println("学生家庭地址:" + stu.getAddress().getAddressName()); transaction.commit();} catch (Exception e) { transaction.rollback();} finally { session.close();}输出结果:Hibernate: select student0_.stuId as stuId1_1_0_, student0_.addressId as addressI6_1_0_, student0_.stuName as stuName2_1_0_, student0_.stuPassword as stuPassw3_1_0_, student0_.stuPic as stuPic4_1_0_, student0_.stuSex as stuSex5_1_0_ from Student student0_ where student0_.stuId=?----------------学生信息---------------学生姓名:Hibernate老大-----------------地址信息-----------------Hibernate: select address0_.addressId as addressI1_0_0_, address0_.addressName as addressN2_0_0_, address0_.descript as descript3_0_0_ from Address address0_ where address0_.addressId=?学生家庭地址:北京Hibernate 分别构建了 2 条简单的查询 Sql 语句,可得出结论:只有当需要获取地址信息时,才会构建 Sql 语句查询地址表;这就是关联映射中的延迟加载。@OneToOne 默认情况下是采用立即策略,通过构建多表查询语句一次性全部查询。
- 2.2 HQL 高级查询 强参数查询使用 SQL 查询时,可以指定查询条件,这个地球人都知道。HQL 中同样能使用条件查询:from Student s where s.stuId> 2在 HQL 中,如果查询条件中的数据需要通过参数传递,则会有两种方案:匿名方案,已经司空见惯,对不对;from Student s where s.stuId> ?命名参数方案。from Student s where s.stuId> :id参数名前面一定要有一个冒号 :id。完整实例献上:String hql="from Student s where s.stuId> :id";Query query=session.createQuery(hql);query.setInteger("id", 2);List<Student> stus= query.list();for (Student student : stus) { ystem.out.println(student);}return null;可自行查看控制台上的输出结果。强命名参数和 ? 占位符作用是一样的,但是,强命名参数可减少指定实参时的出错率。分页查询分页查询是很实用的查询机制。使用原生 SQL 分页查询时,需要自己构建查询 SQL 语句,不同的数据库中的分页查询语句编写也有差异性。Hibernate 通过其提供的分页查询功能很好地避开了这些问题。分页查询之前,先搞清楚几个与查询有关的参数:pageSize: 每一页大小;pageNum: 页码。假如数据库中有 20 行数据,分页查询时指定 pageSize 为 5,则每 5 条数据为一个逻辑页,总共有 4 页。如果要查询第 3 页数据,即 pageNum=3。则需要跳过去的记录数为:(pageNum-1)*pageSize=(3-1)*5=10 ,也就是从第 11 条数据开始查询。现在直接上实例代码:String hql = "from Student s order by stuId" ;Query query = session.createQuery(hql);int pageNum=3;int pageSize=5;int passNum=(pageNum-1)*pageSize;query.setFirstResult(passNum);query.setMaxResults(pageSize);List<Student> stus = query.list();for (Student student : stus) { System.out.println(student.getStuName()); }return null;HIbernate 会从第 11 条记录开始,查询出 5 条记录。针对不同的数据库系统,Hibernate 会给出最佳的 SQL 分页方案。联合查询程序中所需要的数据可不一定在同一张表中,往往都是在多张表中。原生 SQL 通过多表连接或子查询方式解决这个问题。使用 HQL 一样能表达出多表连接的意图。可能你会问:前面的一对一、一对多、多对多映射关联关系后,不就已经能够查询出多张表中的数据吗。如下面表数据:在学生类中采用立即查询策略:@ManyToOne(targetEntity = ClassRoom.class, cascade = CascadeType.REMOVE,fetch=FetchType.EAGER)@JoinColumn(name = "classRoomId")public ClassRoom getClassRoom() { return classRoom;}查询所有学生:String hql = "from Student s";Query query = session.createQuery(hql);List<Student> stus = query.list();System.out.println("-----------------------------");for (Student student : stus) {System.out.println("学生姓名:"+student.getStuName());System.out.println("班级名称: "+student.getClassRoom().getClassRoomName()); }return null;不要怀疑,结果一定是会出现的。但是,可以看到控制台输出了很多 SQL 语句。那是因为,Hibernate 会先查询出所有学生,然后根据班级 ID 再进入班级表进行查询,这就是 Hibernate 查询过程的 1+N 问题。可改成下面的关联查询方式:String hql = "select s.stuName,c.classRoomName from Student s,ClassRoom c where s.classRoom=c";Query query = session.createQuery(hql);List<Object[]> stus = query.list();System.out.println("-----------------------------");for (Object[] student : stus) { System.out.println("学生姓名:"+student[0]); System.out.println("班级名称: "+student[1]); }return null;控制台输入结果:Hibernate: select student0_.stuName as col_0_0_, classroom1_.classRoomName as col_1_0_ from Student student0_ cross join ClassRoom classroom1_ where student0_.classRoomId=classroom1_.classRoomIdHibernate 仅构建了一条 SQL 语句,直接查询出来了所有数据,看得出来,其性能要大于 1+N 方案。HQL 比想象中要简单,比你预期的功能要强大。有了它,再也不怕查询不到我们需要的数据。
- 2. 一对多关联映射 关系型数据库中表与表中的数据存在一对多(或多对一)关系。如学生表、班级表。一个班级有多个学生,多个学生可以在同一个班级。一对多或多对一本质上是一样的,如同一块硬币的正面和反面,只是看待事物的角度不同而已。数据库中有学生表、班级表。使用 Hibernate 进行数据操作时, 程序中就应该有学生类、班级类。同时学生类、班级类应该使用 OOP 语法描述出如同学生表和班级表一样的关系。并且还要让 Hibernate 看得懂。有了前面的基础,直接上代码:创建班级类:@Entitypublic class ClassRoom { private Integer classRoomId; private String classRoomName; private String classRoomDesc; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Integer getClassRoomId() { return classRoomId; }需求:查询学生时,得到学生所在班级信息。进入学生类,添加如下代码,描述学生类和班级类的关系:private ClassRoom classRoom;除此之外,还需要让 Hibernate 知道,这个对象属性的值来自于班级表中的对应数据,进一步修改代码:private ClassRoom classRoom;@ManyToOne(targetEntity=ClassRoom.class)@JoinColumn(name="classRoomId")public ClassRoom getClassRoom() { return classRoom;}@ManyToOne 告诉 Hibernate,从学生的角度来看,学生是多的一边,查询班级表可以得到学生所在班级信息。@JoinColumn 告诉 Hibernate 需要带着指定的字段值到班级表中匹配数据。修改 Hibernate 主配置文件中内容:<property name="hbm2ddl.auto">create</property><mapping class="com.mk.po.Student" /><mapping class="com.mk.po.ClassRoom" />为了让事情变得简单明了,在主配置文件中只保留学生类和班级类的映射关系。学生类中的所有属性描述:private Integer stuId; private String stuName; private String stuSex; private String stuPassword; private Blob stuPic; private ClassRoom classRoom; @ManyToOne(targetEntity=ClassRoom.class) @JoinColumn(name="classRoomId") public ClassRoom getClassRoom() { return classRoom; }使用上一节课的模板对象跑一个空测试实例:@Testpublic void testGetByTemplate() { HibernateTemplate<Student> hibernateTemplate=new HibernateTemplate<Student>(); }目的是让 Hibernate 重新创建学生表、班级表。别忘记啦,自动创建表后,修改回:<property name="hbm2ddl.auto">update</property>进入 MySql,在学生表、班级表中手工添加几条测试数据:到了完成需求的时候,测试下面实例:HibernateTemplate<Student> hibernateTemplate = new HibernateTemplate<Student>(); hibernateTemplate.template(new Notify<Student>() { @Override public Student action(Session session) { Student stu=(Student)session.get(Student.class, new Integer(1)); System.out.println("学生姓名:"+stu.getStuName()); System.out.println("学生所在班级:"+stu.getClassRoom().getClassRoomName()); return stu_; } });控制台输出结果:Hibernate: select student0_.stuId as stuId1_1_1_, student0_.classRoomId as classRoo6_1_1_, student0_.stuName as stuName2_1_1_, student0_.stuPassword as stuPassw3_1_1_, student0_.stuPic as stuPic4_1_1_, student0_.stuSex as stuSex5_1_1_, classroom1_.classRoomId as classRoo1_0_0_, classroom1_.classRoomDesc as classRoo2_0_0_, classroom1_.classRoomName as classRoo3_0_0_ from Student student0_ left outer join ClassRoom classroom1_ on student0_.classRoomId=classroom1_.classRoomId where student0_.stuId=?学生姓名:Hibernate学生所在班级:c1911Hibernate 使用 left outer join 构建了一条多表查询语句!
- 5. 双向多对多映射 前面实现了学生查询到课程,如何在查询课程时,查询到学生信息。很简单,在课程 PO 中,添加学生集合属性: // 学生信息 private Set<Student> students;同样使用 @ManyToMany 注解告诉 Hibernate 数据源头及查询方法:private Set<Student> students;@ManyToMany(targetEntity = Student.class, mappedBy = "courses")public Set<Student> getStudents() { return students;}执行下面的测试实例:HibernateTemplate<Course> hibernateTemplate = new HibernateTemplate<Course>();hibernateTemplate.template(new Notify<Course>() { @Override public Course action(Session session) { Course course=(Course)session.get(Course.class, new Integer(1)); System.out.println("---------------------------"); System.out.println("课程名称:"+course.getCourseName()); System.out.println("----------------------------"); System.out.println("选修此课程的学生数:"+course.getStudents().size()); return course; }});控制台输出结果:Hibernate: select course0_.courseId as courseId1_0_0_, course0_.courseDesc as courseDe2_0_0_, course0_.courseName as courseNa3_0_0_ from Course course0_ where course0_.courseId=?---------------------------课程名称:java----------------------------Hibernate: select students0_.courseId as courseId2_0_1_, students0_.stuId as stuId1_2_1_, student1_.stuId as stuId1_1_0_, student1_.stuName as stuName2_1_0_, student1_.stuPassword as stuPassw3_1_0_, student1_.stuPic as stuPic4_1_0_, student1_.stuSex as stuSex5_1_0_ from score students0_ inner join Student student1_ on students0_.stuId=student1_.stuId where students0_.courseId=?选修此课程的学生数:2同样,Hibernate 采用的是延迟加载模式。先查询课程信息,当开发者需要学生信息时,才构建一条利用中间表进入学生表的 SQL 查询到学生信息。可通过学生表查询到课程表 ,也能从课程表查询到学生表,这种多对多关联映射称为双向映射关联。
hibernate多表关联查询相关搜索
-
h1
h6
hack
hadoop
halt
hana
handler
hanging
hash
hashtable
haskell
hatch
hbase
hbuilder
hdfs
head
header
header php
headers
headerstyle