JPA基础介绍

Part 1

资料参考网址:http://www.cnblogs.com/holbrook/archive/2012/12/30/2839842.html

 

JPA定义了JavaORM及实体操作API的标准。本文摘录了JPA的一些关键信息以备查阅。

如果有hibernate的基础,通过本文也可以快速掌握JPA的基本概念及使用

1JPA概述

JPAJavaPersistenceAPIJava持久化API),定义了对象-关系映射(ORM)以及实体对象持久化的标准接口。

JPAJSR-220EJB3.0)规范的一部分,在JSR-220中规定实体对象(EntityBean)由JPA进行支持。

所以JPA不局限于EJB3.0,而是作为POJO持久化的标准规范,可以脱离容器独立运行,开发和测试更加方便。

JPA在应用中的位置如下图所示:

 

JPA维护一个PersistenceContext(持久化上下文),在持久化上下文中维护实体的生命周期。主要包含三个方面的内容:

1.     ORM元数据。JPA支持annotionxml两种形式描述对象-关系映射。

2.     实体操作API。实现对实体对象的CRUD操作。

3.     查询语言。约定了面向对象的查询语言JPQLJavaPersistenceQueryLanguage)。

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,使用数据库的自增长字段,需要数据库的支持(如SQLServerMySQLDB2Derby等)

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-oneone-to-manymany-to-onemany-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声明自定义关联表,比如BookAuthor之间的关联表:

@JoinTable(name="BOOKAUTHOR",joinColumns={@JoinColumn(name="BOOKID",referencedColumnName="id")},inverseJoinColumns={@JoinColumn(name="AUTHORID",referencedColumnName="id")})

关联关系还可以定制延迟加载和级联操作的行为(owning-sideinverse-side可以分别设置):

通过设置fetch=FetchType.LAZYfetch=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),每个具体类映射到自己的表。

其中12能够支持多态,但是1需要允许字段为NULL2需要多个JOIN关系;3最适合关系数据库,对多态支持不好。具体应用时根据需要取舍。

4事件及监听

通过在实体的方法上标注@PrePersist@PostPersist等声明即可在事件发生时触发这些方法。

5QueryLanguage查询语言

JPA提供两种查询方式,一种是根据主键查询,使用EntityManagerfind方法:

Tfind(ClassentityClass,ObjectprimaryKey)

另一种就是使用JPQL查询语言。JPQL是完全面向对象的,具备继承、多态和关联等特性,和hibernateHQL很相似。

使用EntityManagercreateQuery方法:

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支持AVGSUMCOUNTMAXMIN五个聚合函数。例如:

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中通过EntityManagergetTransaction()方法获取事务的实例(EntityTransaction),之后可以调用事务的begin()commit()rollback()方法。

Date:2012-12-3016:46:29CST

Author:Holbrook

Orgversion7.8.11withEmacsversion24

ValidateXHTML1.0

 

 

Part 2

资料参考网址:http://www.cnblogs.com/jiangxiaoyaoblog/p/5635152.html

正文:

一、HibernateVSMybatis

1、简介

Hibernate对数据库结构提供了较为完整的封装,HibernateO/RMapping实现了POJO和数据库表之间的映射,以及SQL的自动生成和执行。程序员往往只需定义好了POJO到数据库表的映射关系,即可通过Hibernate提供的方法完成持久层操作。程序员甚至不需要对SQL的熟练掌握,Hibernate/OJB会根据制定的存储逻辑,自动生成对应的SQL并调用JDBC接口加以执行。

iBATIS的着力点,则在于POJOSQL之间的映射关系。然后通过映射配置文件,将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调优方案:

MyBatisSession方面和HibernateSession生命周期是一致的,同样需要合理的Session管理机制。MyBatis同样具有二级缓存机制。MyBatis可以进行详细的SQL优化设计。

SQL优化方面:

Hibernate的查询会将表中的所有字段查询出来,这一点会有性能消耗。Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性。而MybatisSQL是手动编写的,所以可以按需求指定查询的字段。

HibernateHQL语句的调优需要将SQL打印出来,而HibernateSQL被很多人嫌弃因为太丑了。MyBatisSQL是自己手动写的所以调整方便。但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,updatedelete语句会刷新缓存。

3.    缓存会使用LeastRecentlyUsed(LRU,最近最少使用的)算法来收回。

4.    根据时间表(比如noFlushInterval,没有刷新间隔),缓存不会以任何时间顺序来刷新。

5.    缓存会存储列表集合或对象(无论查询方法返回什么)1024个引用。

6.    缓存会被视为是read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

所有的这些属性都可以通过缓存元素的属性来修改。

5、总结

Mybatis:小巧、方便、高效、简单、直接、半自动

Hibernate:强大、方便、高效、复杂、绕弯子、全自动

二、Hibernate&JPA

1、JPA

全称JavaPersistenceAPI,通过JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

JPA的出现有两个原因:
其一,简化现有JavaEEJavaSE应用的对象持久化的开发工作;
其二,Sun希望整合对ORM技术,实现持久化领域的统一。

JPA提供的技术:

1ORM映射元数据:JPA支持XMLJDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;

2JPAAPI:用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBCSQL代码中解脱出来。

3)查询语言:通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。

2、JPA&Hibernate关系

JPA是需要Provider来实现其功能的,Hibernate就是JPAProvider中很强的一个。从功能上来说,JPA现在就是Hibernate功能的一个子集。可以简单的理解为JPA是标准接口,Hibernate是实现。Hibernate主要是通过三个组件来实现的,及hibernate-annotationhibernate-entitymanagerhibernate-core

1hibernate-annotationHibernate支持annotation方式配置的基础,它包括了标准的JPAannotation以及Hibernate自身特殊功能的annotation

2hibernate-coreHibernate的核心实现,提供了Hibernate所有的核心功能。

3hibernate-entitymanager实现了标准的JPA,可以把它看成hibernate-coreJPA之间的适配器,它并不直接提供ORM的功能,而是对hibernate-core进行封装,使得Hibernate符合JPA的规范。

总的来说,JPA是规范,Hibernate是框架,JPA是持久化规范,而Hibernate实现了JPA

三、JPA概要

1、概述

JPA在应用中的位置如下图所示:

 

JPA维护一个PersistenceContext(持久化上下文),在持久化上下文中维护实体的生命周期。主要包含三个方面的内容:

1.    ORM元数据。JPA支持annotionxml两种形式描述对象-关系映射。

2.    实体操作API。实现对实体对象的CRUD操作。

3.           查询语言。约定了面向对象的查询语言JPQLJavaPersistenceQueryLanguage

 

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-oneone-to-manymany-to-onemany-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声明自定义关联表,比如BookAuthor之间的关联表:

@JoinTable(name="BOOKAUTHOR",joinColumns={@JoinColumn(name="BOOKID",referencedColumnName="id")},inverseJoinColumns={@JoinColumn(name="AUTHORID",referencedColumnName="id")})

关联关系还可以定制延迟加载和级联操作的行为(owning-sideinverse-side可以分别设置):

通过设置fetch=FetchType.LAZYfetch=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

And

findByLastnameAndFirstname

…wherex.lastname=?1andx.firstname=?2

Or

findByLastnameOrFirstname

…wherex.lastname=?1orx.firstname=?2

Is,Equals

findByFirstname,findByFirstnameIs,findByFirstnameEquals

…wherex.firstname=?1

Between

findByStartDateBetween

…wherex.startDatebetween?1and?2

LessThan

findByAgeLessThan

…wherex.age<?1

LessThanEqual

findByAgeLessThanEqual

…wherex.age?1

GreaterThan

findByAgeGreaterThan

…wherex.age>?1

GreaterThanEqual

findByAgeGreaterThanEqual

…wherex.age>=?1

After

findByStartDateAfter

…wherex.startDate>?1

Before

findByStartDateBefore

…wherex.startDate<?1

IsNull

findByAgeIsNull

…wherex.ageisnull

IsNotNull,NotNull

findByAge(Is)NotNull

…wherex.agenotnull

Like

findByFirstnameLike

…wherex.firstnamelike?1

NotLike

findByFirstnameNotLike

…wherex.firstnamenotlike?1

StartingWith

findByFirstnameStartingWith

…wherex.firstnamelike?1(parameterboundwithappended%)

EndingWith

findByFirstnameEndingWith

…wherex.firstnamelike?1(parameterboundwithprepended%)

Containing

findByFirstnameContaining

…wherex.firstnamelike?1(parameterboundwrappedin%)

OrderBy

findByAgeOrderByLastnameDesc

…wherex.age=?1orderbyx.lastnamedesc

Not

findByLastnameNot

…wherex.lastname<>?1

In

findByAgeIn(Collection<Age>ages)

…wherex.agein?1

NotIn

findByAgeNotIn(Collection<Age>age)

…wherex.agenotin?1

True

findByActiveTrue()

…wherex.active=true

False

findByActiveFalse()

…wherex.active=false

IgnoreCase

findByFirstnameIgnoreCase

…whereUPPER(x.firstame)=UPPER(?1)

 

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:通过EntityManagergetCriteriaBuilderEntityManagerFactorygetCriteriaBuilder方法可以得到CriteriaBuilder对象

2:通过调用CriteriaBuildercreateQuerycreateTupleQuery方法可以获得CriteriaQuery的实例

3:通过调用CriteriaQueryfrom方法可以获得Root实例

过滤条件

1:过滤条件会被应用到SQL语句的FROM子句中。在criteria查询中,查询条件通过PredicateExpression实例应用到CriteriaQuery对象上。

2:这些条件使用CriteriaQuery.where方法应用到CriteriaQuery对象上

3CriteriaBuilder也作为Predicate实例的工厂,通过调用CriteriaBuilder的条件方法(equalnotEqualgtgeltlebetweenlike等)创建Predicate对象。

4:复合的Predicate语句可以使用CriteriaBuilderand,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语句或者上节复杂的连接查询,查出两张或多张表的数据。

法二:映射,接下来将详细介绍。

1ImStudent.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);

 

四、总结

1HibernateDAO层开发比较简单,对于刚接触ORM的人来说,能够简化开发工程,提高开发速度。

2Hibernate对对象的维护和缓存做的很好,对增删改查的对象的维护要方便。

3Hibernate数据库移植性比较好。

4Hibernate功能强大,如果对其熟悉,对其进行一定的封装,那么项目的整个持久层代码会比较简单。

 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值