Part 1
资料参考网址:http://www.cnblogs.com/holbrook/archive/2012/12/30/2839842.html
JPA定义了JavaORM及实体操作API的标准。本文摘录了JPA的一些关键信息以备查阅。
如果有hibernate的基础,通过本文也可以快速掌握JPA的基本概念及使用
1JPA概述
JPA(JavaPersistenceAPI,Java持久化API),定义了对象-关系映射(ORM)以及实体对象持久化的标准接口。
JPA是JSR-220(EJB3.0)规范的一部分,在JSR-220中规定实体对象(EntityBean)由JPA进行支持。
所以JPA不局限于EJB3.0,而是作为POJO持久化的标准规范,可以脱离容器独立运行,开发和测试更加方便。
JPA在应用中的位置如下图所示:
JPA维护一个PersistenceContext(持久化上下文),在持久化上下文中维护实体的生命周期。主要包含三个方面的内容:
1. ORM元数据。JPA支持annotion或xml两种形式描述对象-关系映射。
2. 实体操作API。实现对实体对象的CRUD操作。
3. 查询语言。约定了面向对象的查询语言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中实体的生命周期如下图:
1. New,新创建的实体对象,没有主键(identity)值
2. Managed,对象处于PersistenceContext(持久化上下文)中,被EntityManager管理
3. Detached,对象已经游离到PersistenceContext之外,进入ApplicationDomain
4. Removed,实体对象被删除
EntityManager提供一系列的方法管理实体对象的生命周期,包括:
1. persist,将新创建的或已删除的实体转变为Managed状态,数据存入数据库。
2. remove,删除受控实体
3. merge,将游离实体转变为Managed状态,数据存入数据库。
如果使用了事务管理,则事务的commit/rollback也会改变实体的状态。
3实体关系映射(ORM)
3.1基本映射
对象端 | 数据库端 | annotion | 可选annotion |
Class | Table | @Entity | @Table(name="tablename") |
property | column | – | @Column(name="columnname") |
property | primarykey | @Id | @GeneratedValue详见ID生成策略 |
property | NONE | @Transient |
3.2ID生成策略
ID对应数据库表的主键,是保证唯一性的重要属性。JPA提供了以下几种ID生成策略
1. GeneratorType.AUTO,由JPA自动生成
2. GenerationType.IDENTITY,使用数据库的自增长字段,需要数据库的支持(如SQLServer、MySQL、DB2、Derby等)
3. GenerationType.SEQUENCE,使用数据库的序列号,需要数据库的支持(如Oracle)
4. GenerationType.TABLE,使用指定的数据库表记录ID的增长需要定义一个TableGenerator,在@GeneratedValue中引用。例如:
@TableGenerator(name="myGenerator",table="GENERATORTABLE",pkColumnName="ENTITYNAME",pkColumnValue="MyEntity",valueColumnName="PKVALUE",allocationSize=1)
@GeneratedValue(strategy=GenerationType.TABLE,generator="myGenerator")
3.3关联关系
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-Side |
one-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种操作
3.4继承关系
JPA通过在父类增加@Inheritance(strategy=InheritanceType.xxx)来声明继承关系。A支持3种继承策略:
1. 单表继承(InheritanceType.SINGLETABLE),所有继承树上的类共用一张表,在父类指定(@DiscriminatorColumn)声明并在每个类指定@DiscriminatorValue来区分类型。
2. 类表继承(InheritanceType.JOINED),父子类共同的部分公用一张表,其余部分保存到各自的表,通过join进行关联。
3. 具体表继承(InheritanceType.TABLEPERCLASS),每个具体类映射到自己的表。
其中1和2能够支持多态,但是1需要允许字段为NULL,2需要多个JOIN关系;3最适合关系数据库,对多态支持不好。具体应用时根据需要取舍。
4事件及监听
通过在实体的方法上标注@PrePersist,@PostPersist等声明即可在事件发生时触发这些方法。
5QueryLanguage查询语言
JPA提供两种查询方式,一种是根据主键查询,使用EntityManager的find方法:
Tfind(ClassentityClass,ObjectprimaryKey)
另一种就是使用JPQL查询语言。JPQL是完全面向对象的,具备继承、多态和关联等特性,和hibernateHQL很相似。
使用EntityManager的createQuery方法:
QuerycreateQuery(StringqlString)
5.1使用参数
可以在JPQL语句中使用参数。JPQL支持命名参数和位置参数两种参数,但是在一条JPQL语句中所有的参数只能使用同一种类型。
举例如下:
· 命令参数
Queryquery=em.createQuery("selectpfromPersonpwherep.personid=:Id");query.setParameter("Id",newInteger(1));
· 位置参数
Queryquery=em.createQuery("selectpfromPersonpwherep.personid=?1");query.setParameter(1,newInteger(1));
5.2命名查询
如果某个JPQL语句需要在多个地方使用,还可以使用@NamedQuery或者@NamedQueries在实体对象上预定义命名查询。
在需要调用的地方只要引用该查询的名字即可。
例如:
@NamedQuery(name="getPerson",query="FROMPersonWHEREpersonid=?1")
@NamedQueries({@NamedQuery(name="getPerson1",query="FROMPersonWHEREpersonid=?1"),@NamedQuery(name="getPersonList",query="FROMPersonWHEREage>?1")})
Queryquery=em.createNamedQuery("getPerson");
5.3排序
JPQL也支持排序,类似于SQL中的语法。例如:Queryquery=em.createQuery("selectpfromPersonporderbyp.age,p.birthdaydesc");
5.4聚合查询
JPQL支持AVG、SUM、COUNT、MAX、MIN五个聚合函数。例如:
Queryquery=em.createQuery("selectmax(p.age)fromPersonp");Objectresult=query.getSingleResult();StringmaxAge=result.toString();
5.5更新和删除
JPQL不仅用于查询,还可以用于批量更新和删除。
如:
Queryquery=em.createQuery("updateOrderasoseto.amount=o.amount+10");//update的记录数intresult=query.executeUpdate();
Queryquery=em.createQuery("deletefromOrderItemitemwhereitem.orderin(fromOrderasowhereo.amount<100)");query.executeUpdate();
query=em.createQuery("deletefromOrderasowhereo.amount<100");query.executeUpdate();//delete的记录数
5.6更多
与SQL类似,JPQL还涉及到更多的语法,可以参考:http://docs.oracle.com/cd/E11035_01/kodo41/full/html/ejb3_langref.html
6事务管理
JPA支持本地事务管理(RESOURCELOCAL)和容器事务管理(JTA),容器事务管理只能用在EJB/Web容器环境中。
事务管理的类型可以在persistence.xml文件中的“transaction-type”元素配置。
JPA中通过EntityManager的getTransaction()方法获取事务的实例(EntityTransaction),之后可以调用事务的begin()、commit()、rollback()方法。
Date:2012-12-3016:46:29CST
Author:Holbrook
Orgversion7.8.11withEmacsversion24
Part 2
资料参考网址:http://www.cnblogs.com/jiangxiaoyaoblog/p/5635152.html
正文:
一、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调优方案:
1. 制定合理的缓存策略;
2. 尽量使用延迟加载特性;
3. 采用合理的Session管理机制;
4. 使用批量抓取,设定合理的批处理参数(batch_size);
5. 进行合理的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/>
字面上看就是这样。这个简单语句的效果如下:
1. 映射语句文件中的所有select语句将会被缓存。
2. 映射语句文件中的所有insert,update和delete语句会刷新缓存。
3. 缓存会使用LeastRecentlyUsed(LRU,最近最少使用的)算法来收回。
4. 根据时间表(比如noFlushInterval,没有刷新间隔),缓存不会以任何时间顺序来刷新。
5. 缓存会存储列表集合或对象(无论查询方法返回什么)的1024个引用。
6. 缓存会被视为是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(持久化上下文),在持久化上下文中维护实体的生命周期。主要包含三个方面的内容:
1. ORM元数据。JPA支持annotion或xml两种形式描述对象-关系映射。
2. 实体操作API。实现对实体对象的CRUD操作。
3. 查询语言。约定了面向对象的查询语言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中实体的生命周期如下图:
1. New,新创建的实体对象,没有主键(identity)值
2. Managed,对象处于PersistenceContext(持久化上下文)中,被EntityManager管理
3. Detached,对象已经游离到PersistenceContext之外,进入ApplicationDomain
4. Removed,实体对象被删除
3、实体关系映射(ORM)
1)基本映射
对象端 | 数据库端 | annotion | 可选annotion |
Class | Table | @Entity | @Table(name="tablename") |
property | column | – | @Column(name="columnname") |
property | primarykey | @Id | @GeneratedValue详见ID生成策略 |
property | NONE | @Transient |
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-Side |
one-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根据名称判别
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,CriteriaQuery<?>query,CriteriaBuildercb);
Criteria查询
基本对象的构建
1:通过EntityManager的getCriteriaBuilder或EntityManagerFactory的getCriteriaBuilder方法可以得到CriteriaBuilder对象
2:通过调用CriteriaBuilder的createQuery或createTupleQuery方法可以获得CriteriaQuery的实例
3:通过调用CriteriaQuery的from方法可以获得Root实例
过滤条件
1:过滤条件会被应用到SQL语句的FROM子句中。在criteria查询中,查询条件通过Predicate或Expression实例应用到CriteriaQuery对象上。
2:这些条件使用CriteriaQuery.where方法应用到CriteriaQuery对象上
3:CriteriaBuilder也作为Predicate实例的工厂,通过调用CriteriaBuilder的条件方法(equal,notEqual,gt,ge,lt,le,between,like等)创建Predicate对象。
4:复合的Predicate语句可以使用CriteriaBuilder的and,orandnot方法构建
实例:
ImTeacher.java
@Entity
@Table(name="im_teacher")
publicclassImTeacherimplementsSerializable{
privatestaticfinallongserialVersionUID=1L;
@Id
@GeneratedValue
@Column(name="id")
privateintid;
@Column(name="teacher_id")
privateintteacherId;
@Column(name="name")
privateStringname="";
@Column(name="age")
privateintage;
@Column(name="sex")
privateStringsex="";
...
}
ImTeacherDao.java
publicinterfaceImTeacherDaoextendsPagingAndSortingRepository<ImTeacher,Integer>,JpaSpecificationExecutor{
...
}
@Service
publicclassImTeacherDaoService{
@Autowired
ImTeacherDaoimTeacherDao;
/**
*复杂查询测试
*@parampage
*/
publicPage<ImTeacher>findBySepc(intpage,intsize){
PageRequestpageReq=this.buildPageRequest(page,size);
Page<ImTeacher>imTeachers=this.imTeacherDao.findAll(newMySpec(),pageReq);
returnimTeachers;
}
/**
*建立分页排序请求
*/
privatePageRequestbuildPageRequest(intpage,intsize){
Sortsort=newSort(Direction.DESC,"age");
returnnewPageRequest(page,size,sort);
}
privateclassMySpecimplementsSpecification<ImTeacher>{
@Override
publicPredicatetoPredicate(Root<ImTeacher>root,CriteriaQuery<?>query,CriteriaBuildercb){
//1.混合条件查询
Path<String>exp1=root.get("name");
Path<String>exp2=root.get("age");
query.where(cb.like(exp1,"%王%"),cb.equal(exp2,"45"));
//2.多表查询
/*Join<ImTeacher,ImStudent>join=root.join("imStudent",JoinType.INNER);
Path<String>exp3=join.get("name");
returncb.like(exp3,"%jy%");*/
returnnull;
}
}
}
3.4分页
上个实例的发杂查询已经带有分页,若实例的DAO接口有继承PagingAndSortingRepository接口,则可以直接调用
Page<ImTeacher>impeacher=imTeacherDao.findAll(newPageRequest(1,20));
3.5联表查询
方法:
法一:直接用Query语句或者上节复杂的连接查询,查出两张或多张表的数据。
法二:映射,接下来将详细介绍。
1)ImStudent.java
@Entity
@Table(name="im_student")
publicclassImStudent{
@Id
@GeneratedValue
@Column(name="id")
privateintid;
@Column(name="student_id")
privateintstudentId;
@Column(name="name")
privateStringname="";
@Column(name="age")
privateintage;
@Column(name="sex")
privateStringsex="";
@Column(name="teacher_id")
privateintteacherId;
@ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH})
@JoinColumn(name="teacher_id",referencedColumnName="id",insertable=false,updatable=false)
privateImTeacherimTeacher;
...
}
2)在ImTeacher.java中添加
@OneToMany(mappedBy="imTeacher",cascade=CascadeType.ALL,fetch=FetchType.LAZY)
privateSet<ImStudent>imStudent=newHashSet<ImStudent>();
...
3)根据学生名字查出其老师信息
@Query("SELECTteacherFROMImTeacherteacherJOINteacher.imStudentstudentWHEREstudent.name=:name")
ImTeacherfindByStuName(@Param("name")Stringname);
根据老师名字查出其学生列表
@Query("SELECTstudentFROMImStudentstudentJOINstudent.imTeacherteacherWHEREteacher.name=:name")
Set<ImStudent>findByStudByTeaName(@Param("name")Stringname);
四、总结
1、Hibernate的DAO层开发比较简单,对于刚接触ORM的人来说,能够简化开发工程,提高开发速度。
2、Hibernate对对象的维护和缓存做的很好,对增删改查的对象的维护要方便。
3、Hibernate数据库移植性比较好。
4、Hibernate功能强大,如果对其熟悉,对其进行一定的封装,那么项目的整个持久层代码会比较简单。