何为JPA
JPA全称Java Persistence API,是Sun官方提出的一种ORM规范!
对于Sun官网而言, 一是想简化现有Java EE和Java SE应用开发工作。 二是想整合ORM技术,实现天下归一。
对于JPA规范,都在包路径:javax.persistence.*下,像一些常用的如:@Entity、@Id及@Transient都在此路径下。这些也是一些现在市面上常用的ORM一些约定俗成的注解了。
简单来说,JPA是一套规范。所以使用Jpa的一个好处是,可以更换实现而不必改动太多代码。
JPA与hibernate的关系
JPA规范本质上就是一种ORM规范,注意不是ORM框架——因为JPA并未提供ORM实现,它只是制订了一些规范,提供了一些编程的API接口,但具体实现则由服务厂商来提供实现。
JPA和Hibernate的关系就像JDBC和JDBC驱动的关系,JPA是规范,Hibernate除了作为ORM框架之外,它也是一种JPA实现。JPA怎么取代Hibernate呢?JDBC规范可以驱动底层数据库吗?答案是否定的,也就是说,如果使用JPA规范进行数据库操作,底层需要hibernate作为其实现类完成数据持久化工作。
何为Sping-data-jpa
Spring Data JPA是 Spring Data 的一个子项目, 它通过提供基于 JPA的 Repository 极大地减少了 JPA作为数据访问方案的代码量。Spring Data JPA是Spring基于Hibernate开发的一个JPA框架。可以极大的简化JPA的写法,可以在几乎不用写具体代码的情况下,实现对数据的访问和操作。除了CRUD外,还包括如分页、排序等一些常用的功能。
下面将通过一个完整的例子来说明JPA的使用方式
Spring Data JPA提供的接口,也是Spring Data JPA的核心概念:
- Repository:最顶层的接口,是一个空的接口,目的是为了统一所有Repository的类型,且能让组件扫描的时候自动识别。
- CrudRepository :是Repository的子接口,提供CRUD的功能
- PagingAndSortingRepository:是CrudRepository的子接口,添加分页和排序的功能
- JpaRepository:是PagingAndSortingRepository的子接口,增加了一些实用的功能,比如:批量操3作等。
- JpaSpecificationExecutor:用来做负责查询的接口
- Specification:是Spring Data JPA提供的一个查询规范,要做复杂的查询,只需围绕这个规范来设置查询条件即可。
SpringBoot集成Spring-data-jpa
添加相关依赖
添加spring-boot-starter-data-jpa依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
修改属性配置文件
在属性配置文件中添加 JPA 相关属性,注意这些并非必须,我们如果只添加dataSource 的 url\username\password\driver-class-name 也可以正常使用,有关JPA的其他配置都是可选的。
可以在application.yml文件中配置配置数据源:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1/test?characterEncoding=utf-8&useUnicode=true&serverTimezone=UTC&useSSL=false&autoReconnect=true
username: root
password: 9958
jpa:
database-platform: org.hibernate.dialect.MySQL5Dialect
hibernate:
# ddl-auto: create #每次启动都会重新创建
ddl-auto: update #如果表中有数据就不会重新创建
show-sql: true
也可以在application.properties文件配置mysql的驱动类,数据库地址,数据库账号、密码信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1/test?characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=9958
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
注意,如果通过jpa在数据库中建表,需要将jpa.hibernate.ddl-auto改为create,建完表之后要改为update,否则每次重启工程都会删除表并新建。spring.jap.hibernate.ddl-auto有四个值:
- create: 每次加载 hibernate 时都会删除上一次的生成的表,然后根据你的 model 类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
- create-drop :每次加载 hibernate 时根据 model 类生成表,但是 sessionFactory 一关闭,表就自动删除。
- update:最常用的属性,第一次加载 hibernate 时根据 model 类会自动建立起表的结构(前提是先建立好数据库),以后加载 hibernate 时根据 model 类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
- validate :每次加载 hibernate 时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
创建实体类
传统上,JPA实体类在persistence.xml文件中指定的。使用Spring Boot,这个文件是没有必要的,因为它使用“实体扫描”,默认情况下主配置 @EnableAutoConfiguration 或 @SpringBootApplication 下面的所有包都将会被扫描。任何使用注解 @Entity, @Embeddable 或 @MappedSuperclass 的类都将被管理。
/**
* 通过@Entity 表明是一个映射的实体类, @Id表明id, @GeneratedValue 字段自动生成
*/
@Entity
public class Girl {
@Id
@GeneratedValue
private int id;
private String name;
private int age;
... 省略getter setter
}
Entity 中不映射成列的字段得加 @Transient 注解,不加注解也会映射成列
定义数据访问层
使用 Spring Data JPA建立数据访问层十分简单, 只需定义一个继承 JpaRepository 的接口即可,定义如下:
public interface GirlRepository extends JpaRepository<Girl, Integer> {
}
继承 JpaRepository 接口意味着我们默认已经有了下面的数据访问操作方法:
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();
List<T> findAll(Sort var1);
List<T> findAllById(Iterable<ID> var1);
<S extends T> List<S> saveAll(Iterable<S> var1);
void flush();
<S extends T> S saveAndFlush(S var1);
void deleteInBatch(Iterable<T> var1);
void deleteAllInBatch();
T getOne(ID var1);
<S extends T> List<S> findAll(Example<S> var1);
<S extends T> List<S> findAll(Example<S> var1, Sort var2);
}
定义查询方法
( 1 ) 根据属性名査询
Spring Data JPA支持通过定义在 Repository 接口中的方法名来定义査询,而方法名是根据实体类的属性名来确定的 。
1)常规查询。根据属性名来定义査询方法,示例如下:
/*通过年龄相等查询,参数为age
* 相当于JPQL:select g from Girl g whrer g.age=?1
*/
List<Girl> findByAge(Integer age);
/*通过名字like查询,参数为name
*相当于JPQL:select g from Girl g whrer g.name like ?1
*/
List<Girl> findByNameLike(String name);
从代码可以看出,这里使用了 findBy、 Like、 And这样的关键字。其中 findBy可以用 find、read、 readBy、 query、 queryBy、 get、 getBy来代替。
而 Like和 and这类査询关键字, 如表
2)限制结果数量。结果数量是用 top和 first关键字来实现的,例如:
List<Girl> findFirst10Byname(String name);
List<Girl> findTop20Byname(String name);
(2)使用 JPA的NamedQuery查询
spring Data JpA支持用 JPA的 NameQuery 来定义査询方法,即一个名称映射一个查询语句,在实体类中:
@Entity
@NamedQuery(name = "Girl.findByName", query = "select g from Girl g where g.name=?1")
public class Girl {
..}
调用这条查询语句的方法:
public interface GirlRepository extends JpaRepository<Girl, Integer> {
/*使用NamedQuery里定义的查询语句,而不是根据方法名称查询*/
List<Girl> findByName(String name);
(3)使用@Query 査询
1)使用参数索引 。 Spring Data JPA还支持用@Query注解在接口的方法上实现査询,例如:
@Query("select g from Girl g where g.id=?1")
Optional<Girl> findById(Integer name);
2)使用命名参数。上面的例子是使用参数的索引号来査询的,在 Spring Data JPA里还支持在语句里用名称来匹配査询参数
@Query("select g from Girl g where g.id=:name and g.age=:age")
Optional<Girl> findByName(@Param("name") String name,@Param("age") int age);
3 ) 更新査询。 Sprmg Data JPA支持@Modifying和@Query 注解组合来事件更新查询, 例如
@Modifying
@Transactional
@Query("update Girl g set g.name=?1")
int setName(String name);
其中返回值int表示更新语句影响的行数。
(4)排序与分页
Spring Data JPA充分考虑了在实际开发中所必须的排序和分页的场景,为我们提供了Sort类以及Page接口和Pageable接口
1)定义:
//使用排序
List<Girl> findByName(String name, Sort sort);
//使用分页
List<Girl> findByName(String name, Pageable pageable);
2)使用
//使用排序
List<Girl> findByName(String name, Sort sort);
//使用分页
List<Girl> findByName(String name, Pageable pageable);
2)使用
List<Girl> list1=girlRepository.findByName(name,Sort.by(Sort.Direction.ASC,"age"));
List<Girl> list2=girlRepository.findByName(name, PageRequest.of(0,10));
具体的测试和代码,我就不完全粘贴了,想看的可以直接看我的代码
源码
参考:
http://blog.csdn.net/catoop/article/details/50508397
http://blog.csdn.net/forezp/article/details/70545038
http://www.ityouknow.com/springboot/2016/08/20/spring-boot-jpa.html
https://gitchat.csdn.net/columnTopic/5ab9c2e0c864031e9f8302dc
https://my.oschina.net/xiedeshou/blog/2350428
https://blog.csdn.net/u010412719/article/details/70147824
https://blog.csdn.net/u013030980/article/details/78135335