Spring与Jpa整合

更新时间:2023-08-11 19:36:01 阅读量: 资格考试认证 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

Spring与Jpa整合

Spring与Jpa的整合使用

概述

本文主要基于Oracle的Scott用户下的表作为测试数据库。

如果你尚未安装Oracle,也可以根据如下的表信息,在相应的数据库产品中进行创建。

表结构

主要的表,以EMP和DEPT为主

DEPT表结构

EMP表结构

BONUS表结构

Spring与Jpa整合

SALGRADE表结构

环境准备

Maven设置

在创建项目之前,可以对Maven进行一些必要的设置。如下,

点击Browse浏览,设置setting.xml。在setting.xml中可以设置相应

Spring与Jpa整合

Repository。如下

创建Maven项目

然后,就可以创建一个新的Maven项目,并在pom.xml中添加依赖。所依赖的jar包可以通过/ 查找。为了及时的获得spring或者hibernate的jar包。我们可能还需要在setting.xml文件中添加如下几个<repository>。

以下是Spring的Maven Repository:

For full releases:

Spring与Jpa整合

For milestones:

And for snapshots:

以下是Jboss的Maven Repository

For full releases:

And for snapshots:

Spring与Jpa整合

接下来,引用相应的依赖,首先是spring。关于这一点,可以参考spring的参考手册

Hibernate

。其它依赖根据需要,逐一添加。

以下提供Spring及Hibernate基本依赖:

Spring与Jpa整合

<dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>4.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>1.6.0.RELEASE</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.5.8</version>

Spring与Jpa整合

构建实体

EMP

Spring与Jpa整合

DEPT

Spring与Jpa整合

Jpa实体的注解,需要注意以下几点:

1、 必须要有一个无参的构造函数,如果你需要多个构造函数,那么这个无参的构造函数需

Spring与Jpa整合

要显示的指定,且它应该是protected或private。 2、 枚举类型或者接口不能被指定为实体。

3、 如果实体需要继承某个类的私有化持久状态(即拥有父类中标注有诸如@Column的私有

化属性),只需要在父类上标注@MappedSuperclass即可。通常这样做的目的是,将一些表的公共字段部分抽取出来单独在一个类中声明,避免造成重复声明及类过度冗余。 4、 如果实体类的主键是一个复合主键,需要将作为复合主键的字段单独放在一个类里面。

将这个复合主键类标注@Embeddable,然后在实体类中引用这个复合主键类并标注@EmbeddedId;或者跟一般的实体一样,在为主键的属性上标注@Id,然后于实体类上标注@IdClass指定复合主键类。具体如下示例 Embeddable的形式

Spring与Jpa整合

IdClass形式:

需要注意的是,以下规则适用于复合主键类:

1、 类的访问修饰符必须是public,必须有一个无参的公有的构造方法。 2、 复合主键类必须被序列化,也就是实现Serializable接口。 3、 重写hashCode和equals方法。

Spring与Jpa整合

4、 如果用IdClass的形式,主键类中的属性名称和类型必须和实体类中的属性名称和

类型相同。

5、 另外,如果实体类中在一个集合属性上引用@OneToMany的时候,可以用属性

fetch=ZY表示集合是懒加载的,用mappedBy到实体类中的某个属性,表示由实体类的该属性来维护。标注@OrderBy(“<属性名> <排序方式>, ...”)来表示实体类下的该集合在加载时候的排序方式,可以有多个,用逗号隔开。如Employee类所示。

持久层

Repository接口

1、 我们主要使用Spring Jpa实现对数据持久化的操作。使用Spring Jpa,只需要在接

口中标注@Repository,并声明需要使用到的接口方法,而不用真正的去实现它,因为Spring Jpa已经为我们提供了默认的接口实现类(SimpleJpaRepository)。 2、 通过@Repository注解表示该接口为数据持久化接口。并在Spring的配置文件中声明

<jpa:repositories base-package=”” />(需要引入jpa命名空间)来指定Repository所有的位置,这样它会自动被Spring容器扫描,初始化并管理。 3、 一般地,Repository接口继承了JpaRepository<T, ID>。这个接口已经为我们提供

了一些基本的常用的操作(增删改查),比如通过主键获取实例findOne,获取所有的实例findAll等。详细请参考JpaRepository的API。

现在,如果我们需要一个方法,根据指定的日期,查询出在这个日期之前入职的所有员工,那么我们只需要在EmployeeRepository中声明这样的一个方法:

Spring与Jpa整合

这样,在查询的时候,Spring Jpa就会自动为我们构建如下的jpql查询语句:

于这一点,可以查看

Spring Jpa

的参考手册,

在这里仅列出方法中可使用的关键字:

Keyword Sample

JPQL snippet where stname = ?1 and x.firstname = ?2 where stname = ?1 or x.firstname = ?2

And findByLastnameAndFirstname

Or findByLastnameOrFirstname

Is,Equals

where

findByFirstname,findByFirstnameIs,findByF

x.firstname =

irstnameEquals

1?

where x.startDate between 1? and ?2 where x.age < ?1

where x.age <= ?1 where

Between findByStartDateBetween

LessThan findByAgeLessThan

LessThanEqual findByAgeLessThanEqual GreaterThan

findByAgeGreaterThan

Spring与Jpa整合

Keyword Sample

JPQL snippet x.age > ?1

GreaterThanEq

findByAgeGreaterThanEqual

ual After

findByStartDateAfter

where x.age >= ?1 where x.startDate > ?1

where x.startDate < ?1

where x.age is null where x.age not null where x.firstname like ?1 where x.firstname not like ?1 where x.firstname like ?1 (parameter bound with appended %) where x.firstname like ?1 (parameter bound with prepended %) where x.firstname like ?1 (parameter

Before findByStartDateBefore

IsNull findByAgeIsNull

IsNotNull,Not

findByAge(Is)NotNull

Null Like

findByFirstnameLike

NotLike findByFirstnameNotLike

StartingWith findByFirstnameStartingWith

EndingWith findByFirstnameEndingWith

Containing findByFirstnameContaining

Spring与Jpa整合

Keyword Sample

JPQL

snippet bound

wrapped in %

) where x.age = ?1 order by stname desc where stname <> ?1

where x.age in ?1

where x.age not in ?1 where x.active = true where x.active = false where UPPER(x.firstame) = UPPER(?1)

OrderBy findByAgeOrderByLastnameDesc

Not findByLastnameNot

In NotIn

findByAgeIn(Collection<Age> ages) findByAgeNotIn(Collection<Age> age)

True findByActiveTrue()

False findByActiveFalse()

IgnoreCase findByFirstnameIgnoreCase

当然,我们也可以使用@Query注解。使用方法如下:

Spring与Jpa整合

也可以使用原生的SQL语句,只需要在@Query注解中,添加nativeQuery=true。

在这里需要注意的是,我们使用了#{#entityName}表达式,Spring Jpa会在标有#{#entityName}的地方插入Repository关联的标注有@Entity的实体类名称。也就是说

from #{#entityName} e where e.hireDate <= ?1

from Employee e where e.hireDate <= ?1

完成以上步骤之后,我们不禁会想到,到目前为止,好像都没有配置和数据库关联的相关信息,比如数据源,连接池,是否使用缓存及Hibernate的数据库方言等等。是的,下一步,我们将详细介绍配置与数据库的连接信息。

Persistence.xml配置

因为我们使用的是Jpa,所以首先需要在classpath下的META-INF目录下创建一个persistence.xml文件,在persistence.xml文件中配置Jpa与数据库在连接信息。大致的配置如下:

Spring与Jpa整合

此外,我们使用c3p0作为数据库连接池,所以还要添加以下jar的依赖。

Spring与Jpa整合

可能你已经注意到了,上面被注释掉的关于Hibernate缓存的设置。如果你确实需要

使用Hibernate的缓存,可以将注释去掉,并添加以下的jar依赖。

因为使用的是ehcache缓存框架,所以也需要引用还需要在classpath目录下创建ehcache的配置文件ehcache.xml。

在Spring中装配

如何让Spring管理这个persistence-unit呢。这个自然是在spring的配置文件中配置。大致的配置如下:

Spring与Jpa整合

其中,p命名空间只是为了简化XML文件的配置而作为一个标识使用,它可以使XML文件采用属性配置的方式而非子元素的配置形式(即可以通过p命名空间直接引用属性而不用写properties)。对于字面值属性,其格式为p:属性名 = ”xxx”;对于引用对象的属性,其格式为p:属性名_ref = “xxx”。由于P命名空间的属性名是可变的,所以它没有对应的Schema定义文件,也就是说,在schemaLocation中不用定义p命名空间的Schema文件。

Jpa:repositories指定标注有@Repository的接口所在的包,以便Spring Jpa对这些接口进行相应的解析,构造实例。而context:component-scan则是扫描相应包下的类,以便注册到Spring容器中进行管理。

Spring与Jpa整合

服务层

Service接口及实现

下面简单的写个接口做测试用。

Specifications实现Jpa Criteria

那么问题来了,针对第二个方法的实现,我们要怎么解决呢?因为姓名和雇佣日期作为查询条件不一定有值,也可能是不传值或者传空,不传值的时候就不会作为查询条件去查询。而我们知道spring jpa中会将参数为null的查询条件设置为is null。这样就达不到预期的效果。有两种处理方式:

1、 可以实现方法的重载,实现多个方法,根据参数是否为null,调用不同的查询方法。

Spring与Jpa整合

但是这样同时也会造成接口的冗余。不建议使用。

2、 让Repository实现JpaSpecificationExecutor<T>接口。这个接口提供了几个方法

可供让我们可以用Jpa的Criteria API实现查询条件的构造。

这里我们可能引用到common-lang3里面提供的工具类,所以引用些依赖。

<dependency>

<groupId>mons</groupId> <artifactId>commons-lang3</artifactId> <version>3.3.2</version>

</dependency>

将EmployeeRepository接口修改为:

下面,我们详细看下JpaSpecificationExecutor接口。

本文来源:https://www.bwwdw.com/article/4n1j.html

Top