springhibernatejpa联表查询复杂查询.docx
- 文档编号:16678726
- 上传时间:2023-07-16
- 格式:DOCX
- 页数:20
- 大小:22.55KB
springhibernatejpa联表查询复杂查询.docx
《springhibernatejpa联表查询复杂查询.docx》由会员分享,可在线阅读,更多相关《springhibernatejpa联表查询复杂查询.docx(20页珍藏版)》请在冰点文库上搜索。
springhibernatejpa联表查询复杂查询
SpringHibernateJPA联表查询复杂查询
今天刷网,才发现:
1)如果想用hibernate注解,是不是一定会用到jpa的?
是。
如果hibernate认为jpa的注解够用,就直接用。
否则会弄一个自己的出来作为补充。
2)jpa和hibernate都提供了Entity,我们应该用哪个,还是说可以两个一起用?
Hibernate的Entity是继承了jpa的,所以如果觉得jpa的不够用,直接使用hibernate的即可
正文:
一、HibernateVSMybatis
1、简介
Hibernate对数据库结构提供了较为完整的封装,Hibernate的O/RMapping实现了POJO和数据库表之间的映射,以及SQL的自动生成和执行。
程序员往往只需定义好了POJO到数据库表的映射关系,即可通过Hibernate提供的方法完成持久层操作。
程序员甚至不需要对SQL的熟练掌握,Hibernate/OJB会根据制定的存储逻辑,自动生成对应的SQL并调用JDBC接口加以执行。
iBATIS的着力点,则在于POJO与SQL之间的映射关系。
然后通过映射配置文件,将SQL所需的参数,以及返回的结果字段映射到指定POJO。
相对Hibernate“O/R”而言,iBATIS是一种“SqlMapping”的ORM实现
2、开发对比
Hibernate的真正掌握要比Mybatis来得难些。
Mybatis框架相对简单很容易上手,但也相对简陋些。
个人觉得要用好Mybatis还是首先要先理解好Hibernate。
针对高级查询,Mybatis需要手动编写SQL语句,以及ResultMap。
而Hibernate有良好的映射机制,开发者无需关心SQL的生成与结果映射,可以更专注于业务流程
3、系统调优对比
Hibernate调优方案:
制定合理的缓存策略;尽量使用延迟加载特性;采用合理的Session管理机制;使用批量抓取,设定合理的批处理参数(batch_size);进行合理的O/R映射设计
Mybatis调优方案:
MyBatis在Session方面和Hibernate的Session生命周期是一致的,同样需要合理的Session管理机制。
MyBatis同样具有二级缓存机制。
MyBatis可以进行详细的SQL优化设计。
SQL优化方面:
Hibernate的查询会将表中的所有字段查询出来,这一点会有性能消耗。
Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性。
而Mybatis的SQL是手动编写的,所以可以按需求指定查询的字段。
HibernateHQL语句的调优需要将SQL打印出来,而Hibernate的SQL被很多人嫌弃因为太丑了。
MyBatis的SQL是自己手动写的所以调整方便。
但Hibernate具有自己的日志统计。
Mybatis本身不带日志统计,使用Log4j进行日志记录。
4、缓存机制对比
Hibernate缓存:
Hibernate一级缓存是Session缓存,利用好一级缓存就需要对Session的生命周期进行管理好。
建议在一个Action操作中使用一个Session。
一级缓存需要对Session进行严格管理。
Hibernate二级缓存是SessionFactory级的缓存。
SessionFactory的缓存分为内置缓存和外置缓存。
内置缓存中存放的是SessionFactory对象的一些集合属性包含的数据(映射元素据及预定SQL语句等),对于应用程序来说,它是只读的。
外置缓存中存放的是数据库数据的副本,其作用和一级缓存类似.二级缓存除了以内存作为存储介质外,还可以选用硬盘等外部存储设备。
二级缓存称为进程级缓存或SessionFactory级缓存,它可以被所有session共享,它的生命周期伴随着SessionFactory的生命周期存在和消亡。
Mybatis缓存:
MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。
MyBatis3中的缓存实现的很多改进都已经实现了,使得它更加强大而且易于配置。
默认情况下是没有开启缓存的,除了局部的session缓存,可以增强变现而且处理循环依赖也是必须的。
要开启二级缓存,你需要在你的SQL映射文件中添加一行:
<cache/>
字面上看就是这样。
这个简单语句的效果如下:
映射语句文件中的所有select语句将会被缓存。
映射语句文件中的所有insert,update和delete语句会刷新缓存。
缓存会使用LeastRecentlyUsed(LRU,最近最少使用的)算法来收回。
根据时间表(比如noFlushInterval,没有刷新间隔),缓存不会以任何时间顺序来刷新。
缓存会存储列表集合或对象(无论查询方法返回什么)的1024个引用。
缓存会被视为是read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
所有的这些属性都可以通过缓存元素的属性来修改。
5、总结
Mybatis:
小巧、方便、高效、简单、直接、半自动
Hibernate:
强大、方便、高效、复杂、绕弯子、全自动
二、Hibernate&JPA
1、JPA
全称JavaPersistenceAPI,通过JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
JPA的出现有两个原因:
其一,简化现有JavaEE和JavaSE应用的对象持久化的开发工作;
其二,Sun希望整合对ORM技术,实现持久化领域的统一。
JPA提供的技术:
1)ORM映射元数据:
JPA支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
2)JPA的API:
用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。
3)查询语言:
通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
2、JPA&Hibernate关系
JPA是需要Provider来实现其功能的,Hibernate就是JPAProvider中很强的一个。
从功能上来说,JPA现在就是Hibernate功能的一个子集。
可以简单的理解为JPA是标准接口,Hibernate是实现。
Hibernate主要是通过三个组件来实现的,及hibernate-annotation、hibernate-entitymanager和hibernate-core。
1)hibernate-annotation是Hibernate支持annotation方式配置的基础,它包括了标准的JPAannotation以及Hibernate自身特殊功能的annotation。
2)hibernate-core是Hibernate的核心实现,提供了Hibernate所有的核心功能。
3)hibernate-entitymanager实现了标准的JPA,可以把它看成hibernate-core和JPA之间的适配器,它并不直接提供ORM的功能,而是对hibernate-core进行封装,使得Hibernate符合JPA的规范。
总的来说,JPA是规范,Hibernate是框架,JPA是持久化规范,而Hibernate实现了JPA。
三、JPA概要
1、概述
JPA在应用中的位置如下图所示:
JPA维护一个PersistenceContext(持久化上下文),在持久化上下文中维护实体的生命周期。
主要包含三个方面的内容:
ORM元数据。
JPA支持annotion或xml两种形式描述对象-关系映射。
实体操作API。
实现对实体对象的CRUD操作。
查询语言。
约定了面向对象的查询语言JPQL(JavaPersistenceQueryLanguage。
JPA的主要API都定义在javax.persistence包中。
如果你熟悉Hibernate,可以很容易做出对应:
org.hibernate
javax.persistence
说明cfg.Configuration
Persistence
读取配置信息
SessionFactory
EntityManagerFactory
用于创建会话/实体管理器的工厂类
Session
EntityManager
提供实体操作API,管理事务,创建查询
Transaction
EntityTransaction
管理事务
Query
Query
执行查询2、实体生命周期
实体生命周期是JPA中非常重要的概念,描述了实体对象从创建到受控、从删除到游离的状态变换。
对实体的操作主要就是改变实体的状态。
JPA中实体的生命周期如下图:
New,新创建的实体对象,没有主键(identity)值Managed,对象处于PersistenceContext(持久化上下文)中,被EntityManager管理Detached,对象已经游离到PersistenceContext之外,进入ApplicationDomain
Removed,实体对象被删除
3、实体关系映射(ORM)
1)基本映射
Class
Table
@Entity
@Table(name="tablename")
property
column
–
@Column(name="columnname")
property
primarykey
@Id
@GeneratedValue详见ID生成策略
property
NONE
@Transient
对象端
数据库端
annotion
可选annotion
2)映射关系
JPA定义了one-to-one、one-to-many、many-to-one、many-to-many4种关系。
对于数据库来说,通常在一个表中记录对另一个表的外键关联;对应到实体对象,持有关联数据的一方称为owning-side,另一方称为inverse-side。
为了编程的方便,我们经常会希望在inverse-side也能引用到owning-side的对象,此时就构建了双向关联关系。
在双向关联中,需要在inverse-side定义mappedBy属性,以指明在owning-side是哪一个属性持有的关联数据。
对关联关系映射的要点如下:
关系类型
Owning-Side
Inverse-Sideone-to-one
@OneToOne
@OneToOne(mappedBy="othersideName")
one-to-many/many-to-one
@ManyToOne
@OneToMany(mappedBy="xxx")
many-to-many
@ManyToMany
@ManyToMany(mappedBy="xxx")其中many-to-many关系的owning-side可以使用@JoinTable声明自定义关联表,比如Book和Author之间的关联表:
@JoinTable(name="BOOKAUTHOR",joinColumns={@JoinColumn(name="BOOKID",referencedColumnName="id")},inverseJoinColumns={@JoinColumn(name="AUTHORID",referencedColumnName="id")})
关联关系还可以定制延迟加载和级联操作的行为(owning-side和inverse-side可以分别设置):
通过设置fetch=FetchType.LAZY或fetch=FetchType.EAGER来决定关联对象是延迟加载或立即加载。
通过设置cascade={options}可以设置级联操作的行为,其中options可以是以下组合:
CascadeType.MERGE级联更新CascadeType.PERSIST级联保存CascadeType.REFRESH级联刷新CascadeType.REMOVE级联删除
CascadeType.ALL级联上述4种操作
4、事件及监听
通过在实体的方法上标注@PrePersist,@PostPersist等声明即可在事件发生时触发这些方法。
四、JPA应用
1、Dependencies
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
<dependencies>
2、JPA提供的接口
主要来看看SpringDataJPA提供的接口,也是SpringDataJPA的核心概念:
1):
Repository:
最顶层的接口,是一个空的接口,目的是为了统一所有Repository的类型,且能让组件扫描的时候自动识别。
2):
CrudRepository:
是Repository的子接口,提供CRUD的功能
publicinterfaceCrudRepository<T,IDextendsSerializable>extendsRepository<T,ID>{
<SextendsT>Ssave(Sentity);
TfindOne(IDprimaryKey);
Iterable<T>findAll();
Longcount();
voiddelete(Tentity);
booleanexists(IDprimaryKey);
//…morefunctionalityomitted
}
3):
PagingAndSortingRepository:
是CrudRepository的子接口,添加分页和排序的功能
publicinterfacePagingAndSortingRepository<T,IDextendsSerializable>extendsCrudRepository<T,ID>{
Iterable<T>findAll(Sortsort);
Page<T>findAll(Pageablepageable);
}
4):
JpaRepository:
是PagingAndSortingRepository的子接口,增加了一些实用的功能,比如:
批量操作等。
5):
JpaSpecificationExecutor:
用来做负责查询的接口
publicinterfaceJpaSpecificationExecutor<T>{
TfindOne(Specification<T>spec);
List<T>findAll(Specification<T>spec);
Page<T>findAll(Specification<T>spec,Pageablepageable);
List<T>findAll(Specification<T>spec,Sortsort);
longcount(Specification<T>spec);
}
6):
Specification:
是SpringDataJPA提供的一个查询规范,要做复杂的查询,只需围绕这个规范来设置查询条件即可
3、查询语言
3.1根据名称判别And
findByLastnameAndFirstname
…wherex.lastname=?
1andx.firstname=?
2Or
findByLastnameOrFirstname
…wherex.lastname=?
1orx.firstname=?
2Is,Equals
findByFirstname,findByFirstnameIs,findByFirstnameEquals
…wherex.firstname=?
1Between
findByStartDateBetween
…wherex.startDatebetween?
1and?
2LessThan
findByAgeLessThan
…wherex.age<?
1LessThanEqual
findByAgeLessThanEqual
…wherex.age?
?
1GreaterThan
findByAgeGreaterThan
…wherex.age>?
1GreaterThanEqual
findByAgeGreaterThanEqual
…wherex.age>=?
1After
findByStartDateAfter
…wherex.startDate>?
1Before
findByStartDateBefore
…wherex.startDate<?
1IsNull
findByAgeIsNull
…wherex.ageisnullIsNotNull,NotNull
findByAge(Is)NotNull
…wherex.agenotnullLike
findByFirstnameLike
…wherex.firstnamelike?
1NotLike
findByFirstnameNotLike
…wherex.firstnamenotlike?
1StartingWith
findByFirstnameStartingWith
…wherex.firstnamelike?
1(parameterboundwithappended%)EndingWith
findByFirstnameEndingWith
…wherex.firstnamelike?
1(parameterboundwithprepended%)Containing
findByFirstnameContaining
…wherex.firstnamelike?
1(parameterboundwrappedin%)OrderBy
findByAgeOrderByLastnameDesc
…wherex.age=?
1orderbyx.lastnamedescNot
findByLastnameNot
…wherex.lastname<>?
1In
findByAgeIn(Collection<Age>ages)
…wherex.agein?
1NotIn
findByAgeNotIn(Collection<Age>age)
…wherex.agenotin?
1True
findByActiveTrue()
…wherex.active=trueFalse
findByActiveFalse()
…wherex.active=falseIgnoreCase
findByFirstnameIgnoreCase
…whereUPPER(x.firstame)=UPPER(?
1)Keyword
Sample
JPQLsnippet
3.2@Query
publicinterfaceUserRepositoryextendsJpaRepository<User,Long>{
//Declarequeryatthequerymethodusing@Query
@Query("selectufromUseruwhereu.emailAddress=?
1")
UserfindByEmailAddress(StringemailAddress);
//Advancedlike-expressionsin@Query
@Query("selectufromUseruwhereu.firstnamelike%?
1")
List<User>findByFirstnameEndsWith(Stringfirstname);
//Declareanativequeryatthequerymethodusing@Query
@Query(value="SELECT*FROMUSERSWHEREEMAIL_ADDRESS=?
1",nativeQuery=true)
UserfindByEmailAddress(StringemailAddress);
//Declarenativecountqueriesforpaginationatthequerymethodusing@Query
@Query(value="SELECT*FROMUSERSWHERELASTNAME=?
1",countQuery="SELECTcount(*)FROMUSERSWHERELASTNAME=?
1",nativeQuery=true)
Page<User>findByLastname(Stringlastname,Pageablepageable);
//Declaringmanipulatingqueries
@Modifying
@Query("updateUserusetu.firstname=?
1whereu.lastname=?
2")
intsetFixedFirstnameFor(Stringfirstname,Stringlastname);
}
3.3复杂查询JpaSpecificationExecutor
Criteria查询:
是一种类型安全和更面向对象的查询
这个接口基本是围绕着Specification接口来定义的,Specification接口中只定义了如下一个方法:
PredicatetoPredicate(Root<T>root,CriteriaQu
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- springhibernatejpa 查询 复杂
![提示](https://static.bingdoc.com/images/bang_tan.gif)