Spring Data JPA快速入门

Spring Data Jpa

概述

简介

Spring Data JPA 是一套基于ORM(对象关系映射)框架,JPA规范封装的一套JPA应用框架.开发者可以用极简的代码即可实现对数据的访问和操作.它提供了包括增删改查等在内的常用功能,切易于扩展.

使用Spring Data JPA 可以极大的提高开发效率.

常见的ORM框架有Hibernate,Mybatis,topLink等等.

 

Spring Data JPA的内容

Spring Data JPA提供的编程接口:

1.Repository:最顶层的接口,是一个空接口.目的是为了统一索引的Repository的类型,且能让组件扫描的时候自动识别.

2:CrudRepository :是Repository的子接口,提供CRUD的功能

3:PagingAndSortingRepository:是CrudRepository的子接口,添加分页和排序的功能

4:JpaRepository:是PagingAndSortingRepository的子接口,增加了一些实用的功能,比如:批量操作等。

5:JpaSpecificationExecutor:用来做复杂查询的接口

6:Specification:是Spring Data JPA提供的一个查询规范,要做复杂的查询,只需围绕这个规范来设置查询条件即可

Spring Data JPA快速入门 

Jpa Specification Executor接口与左边的接口没有直接继承关系,它是作为一个辅助接口使用的.

快速入门

搭建用户管理项目,具体分为以下步骤:

1. 建立工程

2. 导入所有配置

3. 配置与编码

建立工程

准备开发工具

开发工具Eclipse,MySql数据库,数据库管理工具Navicat

创建数据库及表格

建立数据库: user_manage

建立数据表:user

在Eclipse中建立java工程

创建工程结构

Spring Data JPA快速入门 

应用重要的几个层次及调用关系图

中间的三个层次是项目的核心层次,是我们构建项目mvc的核心,我们基于这些层次确定包结构:

***.repository ---- 存放自定义的数据操作接口,相当于dao

***.service ---- 存放服务层的接口和实现

***.controller ---- 存放控制器类

***.model ---- 存放实体类

***.exception ---- 存放异常类

***.test ---- 存放测试类

引入所需的jar包

本项目使用maven创建工程,pom.xml中配置jar包的依赖:

<!-- spring相关的依赖,必须统一版本号,防止版本冲突 -->

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context-support</artifactId>

<version>4.1.6.RELEASE</version>

</dependency>

 

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-webmvc</artifactId>

<version>4.1.6.RELEASE</version>

</dependency>

 

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-test</artifactId>

<version>4.1.6.RELEASE</version>

</dependency>

 

<!-- spring Data JPA的依赖 -->

<dependency>

<groupId>org.springframework.data</groupId>

<artifactId>spring-data-jpa</artifactId>

<version>1.7.2.RELEASE</version>

</dependency>

 

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-entitymanager</artifactId>

<version>3.6.10.Final</version>

</dependency>

 

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-ehcache</artifactId>

<version>3.6.10.Final</version>

</dependency>

 

<!-- commons依赖 -->

<dependency>

<groupId>commons-logging</groupId>

<artifactId>commons-logging-api</artifactId>

<version>1.1</version>

</dependency>

 

<dependency>

<groupId>commons-fileupload</groupId>

<artifactId>commons-fileupload</artifactId>

<version>1.2.2</version>

</dependency>

 

<dependency>

<groupId>commons-io</groupId>

<artifactId>commons-io</artifactId>

<version>2.0.1</version>

</dependency>

 

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>servlet-api</artifactId>

<version>2.5</version>

</dependency>

 

<dependency>

<groupId>net.sf.json-lib</groupId>

<artifactId>json-lib</artifactId>

<classifier>jdk15</classifier>

<version>2.3</version>

</dependency>

 

<!-- 数据库相关依赖 -->

<dependency>

<groupId>c3p0</groupId>

<artifactId>c3p0</artifactId>

<version>0.9.1.2</version>

</dependency>

 

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>5.1.5</version>

</dependency>

 

<!-- 日志依赖 -->

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-nop</artifactId>

<version>1.5.8</version>

</dependency>

 

配置与编码

创建配置: application.xml ---- Spring上下文

 Persistence.xml ---- 管理持久化

 

Persistence.xml :

<?xml version="1.0" encoding="UTF-8"?>

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">  

<persistence-unit name="userPU" transaction-type="RESOURCE_LOCAL">

<provider >org.hibernate.ejb.HibernatePersistence</provider>

<properties>

<!-- 配置数据库连接信息 -->

<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>

<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/user_manage"/>

<property name="hibernate.connection.username" value="root"/>

<property name="hibernate.connection.password" value="root"/>

<!-- 配置Hibernate的方言 -->

<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>

 

<!-- hibernate日志输出配置 -->

<property name="hibernate.show_sql" value="true"/>

<property name="hibernate.format_sql" value="true"/>

<property name="hibernate.use_sql_comments" value="true"/>

 

<!-- 根据java模型生成数据库表结构的策略 -->

<property name="hibernate.hbm2ddl.auto" value="update"/>

<!-- 命名策略 : 驼峰命名法-->

<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"></property>

 

</properties>

</persistence-unit>

 

</persistence>

 

Application.xml :

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

    xmlns:context="http://www.springframework.org/schema/context"   

    xmlns:jdbc="http://www.springframework.org/schema/jdbc"    

    xmlns:jee="http://www.springframework.org/schema/jee"   

    xmlns:tx="http://www.springframework.org/schema/tx"  

    xmlns:jpa="http://www.springframework.org/schema/data/jpa"  

    xsi:schemaLocation="  

        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  

        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd  

        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd  

        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd  

        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd  

        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"  

    default-lazy-init="true">

 

    <!--第一步-->

    <!--定义服务层代码存放的包扫描路径-->

<context:component-scan base-package="cn.wxdl.usermanage.service" />

 

    <!--第二步-->

    <!--定义实体的工厂bean-->

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

        <property name="persistenceUnitName" value="userPU" />

        <property name="persistenceXmlLocation" value="classpath:persistence1.xml"></property>

    </bean>

 

    <!--第三步-->

    <!--定义事务管理器-->

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">

        <property name="entityManagerFactory" ref="entityManagerFactory"/>

    </bean>

 

    <!--第四步-->

    <!--定义repository接口的存放目录-->

    <!--定义接口实现的后缀,通常用Impl-->

    <!--定义实体工厂的引用-->

    <!--定义事务管理器的引用-->

    <jpa:repositories base-package="cn.wxdl.usermanage.repository"

      repository-impl-postfix="Impl" 

      entity-manager-factory-ref="entityManagerFactory" 

      transaction-manager-ref="transactionManager"/>

 

    <!--第五步-->

    <!--声明采用注解的方式申明事务-->

    <tx:annotation-driven transaction-manager="transactionManager"/>

 

</beans>

 

创建类文件并编码

User.java ---- 用户实体类

UserRepository.java ---- 用户的数据接口

UserService.java ---- 用户服务接口

UserServiceImpl.java ---- 接口实现

UserNotFound.java ---- 异常类,未找到记录时抛出

 

类之间的关系:

Spring Data JPA快速入门 

实体中常用的注解:

· @ Entity :声明这个类是一个实体类

· @ Table:指定映射到数据库的表格

· @ Id :映射到数据库表的主键属性,一个实体只能有一个属性被映射为主键

· @ GeneratedValue:主键的生成策略

@Entity //这是一个实体类

@Table (name="user") //对应的表名是user

public class User {

@Id //此字段是主键

@GeneratedValue //给定默认的生成策略

private Integer id;

private String name;

private String address;

private String phone;

....实现getter 和 setter 方法...

}

 

JpaRepository接口常用的方法:

· delete删除或批量删除

· findAll查找所有

· findO ne查找单个

· save保存单个或批量保存

· saveAndFlush保存并刷新到数据库

UserRepository.class

 /**注:继承的接口是个泛型 -- 第一个参数是实体类类型.第二个参数是主键类型 */

public interface UserRepository extends JpaRepository<User, Integer>{

//此处是空实现,可以根据需求添加方法

}

 

UserService.class

public interface UserService {

//添加

public void addUser(User user);

//修改

public User updateUser(User user) throws UserNotFound;

//删除

public User deleteUserById(Integer id) throws UserNotFound;

//根据id查询单条记录

public User getUser(Integer id);

//查询多条记录

public List<User> getUsers();

//根据id判断记录是否存在

public boolean existById(Integer id);

public List<User> pageUsers(Pageable pageable);

}

 

UserServiceImpl.class

@Service ("userService")

public class UserServiceImpl implements UserService{

//关联了UserRepository 同等与注入dao层的实例

@Autowired

private UserRepository userRepository;

 

public void addUser(User user) {

 

userRepository.save(user);

}

//实现UserService中定义的方法

}

 

之后就可以自己动手写个测试方法进行测试

查询操作的基本实现的方式

· 基于方法名解析的概念

· 方法名 构造方法

· 目前支持的 关键词

· 嵌套实体方法命名规则

 

基于方法名解析的概念

JpaRepository支持接口规范方法名查询。意思是如果在接口中定义的查询方法符合它的命名规则,就可以不用写实现。

例如:findByName这个方法表示从数据库中查询Name这个属性等于XXX的所有记录,类似于SQ L语句:select * from xxTable where name=xxx这种形式

这段话有两个重点:

1、方法名需要在接口中设定

2、必须符合一定的命名规范

 

方法名构造方法

find+全局修饰+By+实体的属性名称+限定词+连接词+ ...(其它实体属性)+O rderBy+

排序属性+排序方向

例如:

  findDistinctByFirstNameIgnoreCaseAndLastNameOrderByAgeDesc(StringfirstName,String lastName){......}

其中:Distinct是全局修饰(非必须),FirstName和LastName是实体的属性名,

And是连接词,IgnoreCase是限定词,Age是排序属性,Desc是排序方向,限定词

和连接词统称为“关键词”

 

目前支持的关键词

常用词如下:

全局修饰:Distinct,Top,First

关键词:IsN ull,IsN otN ull,Like,N otLike,Containing,In,N otIn,

IgnoreCase,Betw een,Equals,LessThan,GreaterThan,After,Before...

排序方向:Asc,Desc

连接词:And,O r

Spring Data JPA快速入门

Spring Data JPA快速入门

更多关键词请查看官方在线文档:

http://docs.spring.io/spring-data/jpa/docs/1.7.2.RELEASE/reference/html/

使用@Query

可以在自定义的查询方法上使用@Query来指定该方法要执行的查询语句

public interface UserRepository extends JpaRepository<User, Integer>{

@Query("select u from User u where u.name = ?1")

public List<User> queryByName(String username);

}

 

注意:

1:方法的参数个数必须和@Query里面需要的参数个数一致

2:如果是like,后面的参数需要前面或者后面加“%”

 

使用@Param可以用命名参数来代替位置编号,将方法参数与 JPQL 中的命名参数对应。JPQL 语句中通过": 变量"的格式来指定参数

例:

public interface UserRepository extends JpaRepository<User, Integer> {

@Query("select u from User u where u.name = :name and u.phone = :phone")

public List<User> queryUser(@Param("name")String name,@Param("phone")String phonenum);

}

 

如果要生成更新类的Query语句,在@Query之前添加@Modifying即可。

例:

@Modifying

@Query("update User u set u.firstname = ?1 where u.lastname = ?2")

int setFixedFirstnameFor(String firstname, String lastname);

注意:

1:方法的返回值应该是int,表示更新语句所影响的行数。

2:在调用的地方必须加事务,没有事务不能正常执行。

使用JPA NamedQueries

JPA配置文件中定义

META-INF文件下的JPA的配置文件orm.xml中,通过<named-query/>元素进行定义。

例:

<named-query name="User.findByLastname">

  <query>select u from User u where u.lastname = ?1</query>

</named-query>

 

通过Annotation配置

Entity Bean中使用@NamedQuery(或@NamedNativeQuery)进行配置。

例:

@Entity

@NamedQuery(name = "User.findByEmailAddress",

  query = "select u from User u where u.emailAddress = ?1")

public class User {

}

 

注意

 上述两种方法都需要满足”DomainClass.methodName()的命名规则。

 无论是在JPA配置文件中使用<named-query/>定义还是在Entity Bean中使用@NamedQuery进行配置,

   在持久层的接口中必须声明对应的方法, 例:

public interface UserRepository extends JpaRepository<User, Long> {

List<User> findByLastname(String lastname);

User findByEmailAddress(String emailAddress);

}

 

创建Query的策略

创建Query的策略有如下3种:

Ø  create:只通过解析方法名来创建Query。忽略@Query和NamedQuery方法。

Ø  use-declared-query:如果方法通过 @Query 指定了查询语句,则使用该语句创建Query;如果没有,则查找是否定义了符合条件的Named Query,如果找到,则使用该命名查询;如果两者都没有找到,则抛出异常。

Ø  create-if-not-found (default):如果方法通过 @Query 指定了查询语句,则使用该语句创建查询;如果没有,则查找是否定义了符合条件的Named Query,如果找到,则使用该Named Query;如果两者都没有找到,则通过解析方法名字来创建Query。

 

<jpa:repositories>中提供的query-lookup-strategy 属性可以用来定义查找Query的顺序。定义方法如下:

<jpa:repositories base-package=" com.jpa.data.sample" query-lookup-strategy="create"/>

嵌套实体方法命名规则

构词法:主实体中子实体的名称+ _ +子实体的属性名称

例如:List<Person> findByAddress_ZipCode(ZipCode zipCode)

表示查询所有 Address(地址)的zipCode(邮编)为指定值的所有Person(人员)

转载于:https://my.oschina.net/wxdl/blog/700809