SpringBoot引入Spring Data JPA

本文标题:SpringBoot引入Spring Data JPA
原始链接: https://shuibo.cn/04-spring-boot-spring-data-jpa.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。



1. Jpa介绍

    JPA(Java Persistence API)是一种Java持久化解决方案,是Sun官方在JDK5.0后提出的规范(JSR388,接口包在javax.persistence),不是一个产品,例如Hibernate是产品。

JPA是在吸收现有ORM框架的基础上发展而来,总得包括以下:

  • ORM映射:支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系
  • API:操作实体对象来执行CRUD操作
  • 查询语言:通过面向对象而非面向数据库的查询语言(JPQL)查询数据,避免程序的SQL语句紧密耦合

2. 什么是Spring Data Jpa

    Spring Data Jpa是Spring Data家族的一部分,Spring Data JPA相对于Java EE中的JPA,配置更简单,以轻量级的方式实现了部分在 EJB 容器环境下才具有的功能,将 EntityManager 的创建与销毁、事务管理等代码抽取出来,并由其统一管理,并且极大的简化了数据库访问层的代码。
Spring Data包含众多子项目除了JPA还有Spring Data MongoDB等等

3. 引入Spring Data Jpa

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

创建Test表(略),设置数据库链接

spring:
  datasource:
    url:  jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
    username: root
    password: root
  jpa:
    database: mysql
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
    show-sql: true
    hibernate:
      ddl-auto: update
        # create: 每次运行程序时,都会重新创建表,故而数据会丢失
        # create-drop: 每次运行程序时会先创建表结构,然后待程序结束时清空表
        # upadte: 每次运行程序,没有表时会创建表,如果对象发生改变会更新表结构,原有数据不会清空,只会更新(推荐使用)
        # validate: 运行程序会校验数据与数据库的字段类型是否相同,字段不同会报错
        # none: 禁用DDL处理

4. 使用Spring Data Jpa增删改查

  • 实体类
@Entity
@Table(name = "t_test")
public class Test {

    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "username", unique = true, nullable = false, length = 64)
    private String username;

    @Column(name = "age",unique = true)
    private Integer age;

    // 忽略 Get Set 方法
     . . .
}
  • 建立数据库访问层

      使用Spring Data JPA建立数据库十分简单,只需要定义一个继承了JpaRepository的接口

public interface TestJpaRepository extends JpaRepository<Test, Long> {}

      继承了JpaRepository就相当于有了下面的数据访问操作方法,这些都是Spring Data Jpa封装好的。

@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);
}

Jpa三种查询方法介绍

1.方法命名查询

/**
 * 通过username查询
 * @param username username
 * @return
 */
List<Test> findByUsername(String username);

/**
 * 通过username + age查询
 * @param username username
 * @param age age
 * @return
 */
List<Test> findByUsernameAndAge(String username,Integer age);

/**
 * 查询符合年龄条件的前10条数据
 * @param age
 * @return
 */
List<Test> findFirst10ByAge(Integer age);

/**
 * 查询符合Name条件的前10条数据
 * @param username
 * @return
 */
List<Test> findTop10ByUsername(String username);

2.@NamedQuery查询

   Spring Data JPA 支持@NameQuery来定义查询方法,即一个名称映射一个查询语句(要在实体类上写,不是接口里写)

@Entity
@Table(name = "t_test")
@NamedQuery(name="findByAge", query="select t from Test t where t.age=?1")
public class Test {
    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "username", unique = true, nullable = false, length = 64)
    private String username;

    @Column(name = "age",unique = true)
    private Integer age;
}

如果要定义多个命名查询,需要使用@NamedQueries

@Entity
@Table(name = "t_test")
@NamedQuery(name="findByAge", query="select t from Test t where t.age=?1")
@NamedQueries({
        @NamedQuery(name="findAllTest",query="select t from Test t"),
        @NamedQuery(name="findTestWithId",query="SELECT t FROM Test t WHERE t.id = ?1"),
        @NamedQuery(name="findTestWithUsername",query="SELECT t FROM Test t WHERE t.username = :username")
})
public class Test {
    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "username", unique = true, nullable = false, length = 64)
    private String username;

    @Column(name = "age",unique = true)
    private Integer age;

调用时:

EntityManager em = emf.createEntityManager();
List<Test> tests = em.createNamedQuery("findAllTest").getResultList();//根据Test实体中定义的命名查询

EntityManager em = emf.createEntityManager();
Query query =  em.createNamedQuery("findTestWithId");//根据Test实体中定义的命名查询
query.setParameter(1, 2L);
List<Test> tests = query.getResultList();

3.@Query查询

   Spring Data JPA 支持@Query来定义查询方法

@Query("select t from Test t where t.username=?1 and t.age=?2")
List<Test> getAllByUsernameAndAge(String username,Integer age);

Spring Data JPA支持使用@Modifying和@Query注解组合来进行更新查询

// int表示的是更新语句所影响的行数
@Modifying
@Query("update Test t set t.username=?1")
int setUserName(String username);
testJpaRepository.findAll();
// 根据id查询
testJpaRepository.getOne(1L);
// 增加
testJpaRepository.save(test);
// 删除
testJpaRepository.delete(test);
// 数据数量(条)
testJpaRepository.count();
...
...
...

支持的关键字、示例及JPQL片段如下表所示:

Keyword Sample JPQL Snippet
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is,Equals indByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull findByAgeIsNull … where x.age is null
IsNotNull,NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike ... findByFirstnameNotLike
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection<Age> ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection<Age> ages) … where x.age not in ?1
True findByActiveTrue() … where x.active = true
False findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)
... ... ...

具体Spring Data Jpa对方法名的解析规则可参看官方文档4.4.3. Property Expressions

5. 小结

    本篇内容主要介绍了在Spring Boot中引入Spring Data JPA以及JPA的简单基础引用,本篇未及地方日后有空再补。
本文GitHub地址:https://github.com/ishuibo/SpringAll

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356

推荐阅读更多精彩内容