主角的理解子句怎么写的是什么?

有很多读者留言希望松哥能好好聊聊 Spring Data Jpa! 其实这个话题松哥以前零零散散的介绍过,在我的书里也有介绍过,但是在公众号中还没和大伙聊过,因此本文就和大家来仔细聊聊 Spring Data 和 Jpa!

  • 可以看到,实现类不少。那么到底如何理解 Repository 呢?

  • 若我们定义的接口继承了 Repository, 则该接口会被 IOC 容器识别为一个 Repository Bean,进而纳入到 IOC 容器中,进而可以在该接口中定义满足一定规范的方法。
  • Spring Data可以让我们只定义接口,只要遵循 Spring Data 的规范,就无需写实现类。
  • 基础的 Repository 提供了最基本的数据访问功能,其几个子接口则扩展了一些功能,它的几个常用的实现类如下:

    • 涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性以首字母大写

    例如:定义一个 Entity 实体类:

    使用 And 条件连接时,条件的属性名称与个数要与参数的位置与个数一一对应,如下:

    • 支持属性的级联查询. 若当前类有符合条件的属性, 则优先使用, 而不使用级联属性. 若需要使用级联属性, 则属性之间使用 _ 进行连接.
    • 查询所有年龄小于 90 岁的人
    • 查询所有姓赵的、并且 id 大于 50 的人
    • 查询所有姓名中包含"上"字的人
    • 查询所有姓赵的或者年龄大于 90 岁的
    • 查询所有角色为 1 的用户

    支持的查询关键字如下图:

    为什么写上方法名,JPA就知道你想干嘛了呢?假如创建如下的查询:findByUserDepUuid(),框架在解析该方法时,首先剔除 findBy,然后对剩下的属性进行解析,假设查询实体为Doc:

    1. 先判断 userDepUuid (根据 POJO 规范,首字母变为小写)是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步;
    2. 从右往左截取第一个大写字母开头的字符串(此处为 Uuid),然后检查剩下的字符串是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,则重复第二步,继续从右往左截取;最后假设 user 为查询实体的一个属性;
    3. 接着处理剩下部分(DepUuid),先判断 user 所对应的类型是否有depUuid属性,如果有,则表示该方法最终是根据 “ Doc.user.depUuid” 的取值进行查询;否则继续按照步骤 2 的规则从右往左截取,最终表示根据 “Doc.user.dep.uuid” 的值进行查询。
    4. 还有一些特殊的参数:例如分页或排序的参数:

    有的时候,这里提供的查询关键字并不能满足我们的查询需求,这个时候就可以使用 @Query 关键字,来自定义查询 SQL,例如查询 Id 最大的 User:

    如果查询有参数的话,参数有两种不同的传递方式,

    • 利用下标索引传参,索引参数如下所示,索引值从1开始,查询中 ”?X” 个数需要与方法定义的参数个数相一致,并且顺序也要一致:
    • 命名参数(推荐):这种方式可以定义好参数名,赋值时采用@Param(“参数名”),而不用管顺序:

    查询时候,也可以是使用原生的 SQL 查询,如下:

    涉及到数据修改操作,可以使用 @Modifying 注解,@Query 与 @Modifying 这两个 annotation 一起声明,可定义个性化更新操作,例如涉及某些字段更新时最为常用,示例如下:

    1. 方法的返回值应该是 int,表示更新语句所影响的行数
    2. 在调用的地方必须加事务,没有事务不能正常执行
    3. 默认情况下, Spring Data 的每个方法上有事务, 但都是一个只读事务. 他们不能完成修改操作

    说到这里,再来顺便说说 Spring Data 中的事务问题:

    1. Spring Data 提供了默认的事务处理方式,即所有的查询均声明为只读事务。
    2. 对于自定义的方法,如需改变 Spring Data 提供的事务默认方式,可以在方法上添加 @Transactional 注解。
    3. 进行多个 Repository 操作时,也应该使它们在同一个事务中处理,按照分层架构的思想,这部分属于业务逻辑层,因此,需要在Service 层实现对多个 Repository 的调用,并在相应的方法上声明事务。

    关注公众号【江南一点雨】,专注于 Spring Boot+微服务以及前后端分离等全栈技术,定期视频教程分享,关注后回复 Java ,领取松哥为你精心准备的 Java 干货!

有很多读者留言希望松哥能好好聊聊 Spring Data Jpa!其实这个话题松哥以前零零散散的介绍过,在我的书里也有介绍过,但是在公众号中还没和大伙聊过,因此本文就和大家来仔细聊聊 Spring Data 和 Jpa!



MIT 为直到提交事务时才更新数据库记录。

  • 设置与查询对象相关的特定供应商参数或提示信息。参数名及其取值需要参考特定 JPA 实现库提供商的文档。如果第二个参数无效将抛出IllegalArgumentException异常。
  • 为查询语句的指定位置参数赋值。Position 指定参数序号,value 为赋给参数的值。
  • 为查询语句的指定位置参数赋 Calenda r值。position 指定参数序号,value 为赋给参数的值,temporalType 的含义及取舍同前。
  • 为查询语句的指定名称参数赋值。
  • 为查询语句的指定名称参数赋 Date 值,用法同前。
  • 为查询语句的指定名称参数设置Calendar值。name为参数名,其它同前。该方法调用时如果参数位置或参数名不正确,或者所赋的参数值类型不匹配,将抛出 IllegalArgumentException 异常。
  1. from 子句是查询语句的必选子句。
  2. select 用来指定查询返回的结果实体或实体的某些属性。
  3. from 子句声明查询源实体类,并指定标识符变量(相当于SQL表的别名)。
  4. 如果不希望返回重复实体,可使用关键字 distinct 修饰。select、from 都是 JPQL 的关键字,通常全大写或全小写,建议不要大小写混用。

其他方法的与此类似,这里不再赘述。

在 Spring Boot 中,Spring Data Jpa 官方封装了太多东西了,导致很多人用的时候不知道底层到底是怎么配置的,本文就和大伙来看看在手工的Spring环境下,Spring Data Jpa要怎么配置,配置完成后,用法和 Spring Boot 中的用法是一致的。

首先创建一个普通的Maven工程,并添加如下依赖:

接下来创建一个 User 实体类,创建方式参考 Jpa中实体类的创建方式,这里不再赘述。

这里和 Jpa 相关的配置主要是三个,一个是entityManagerFactory,一个是Jpa的事务,还有一个是配置dao的位置,配置完成后,就可以在 org.sang.dao 包下创建相应的 Repository 了,如下:

getUserById表示根据id去查询User对象,只要我们的方法名称符合类似的规范,就不需要写SQL,具体的规范一会来说。好了,接下来,创建 Service 和 Controller 来调用这个方法,如下:

这样,就可以查询到id为1的用户了。

首先来看 Repository 的一个继承关系图:

可以看到,实现类不少。那么到底如何理解 Repository 呢?

  1. 若我们定义的接口继承了 Repository, 则该接口会被 IOC 容器识别为一个 Repository Bean,进而纳入到 IOC 容器中,进而可以在该接口中定义满足一定规范的方法。
  2. Spring Data可以让我们只定义接口,只要遵循 Spring Data 的规范,就无需写实现类。

基础的 Repository 提供了最基本的数据访问功能,其几个子接口则扩展了一些功能,它的几个常用的实现类如下:

  • 涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性以首字母大写

例如:定义一个 Entity 实体类:

使用And条件连接时,条件的属性名称与个数要与参数的位置与个数一一对应,如下:

  • 支持属性的级联查询. 若当前类有符合条件的属性, 则优先使用, 而不使用级联属性. 若需要使用级联属性, 则属性之间使用 _ 进行连接.

2.查询所有年龄小于90岁的人

4.查询所有姓赵的、并且id大于50的人

5.查询所有姓名中包含”上”字的人

6.查询所有姓赵的或者年龄大于90岁的

7.查询所有角色为1的用户

支持的查询关键字如下图:

为什么写上方法名,JPA就知道你想干嘛了呢?假如创建如下的查询:findByUserDepUuid(),框架在解析该方法时,首先剔除 findBy,然后对剩下的属性进行解析,假设查询实体为Doc:

  1. 先判断 userDepUuid (根据 POJO 规范,首字母变为小写)是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步;
  2. 从右往左截取第一个大写字母开头的字符串(此处为Uuid),然后检查剩下的字符串是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,则重复第二步,继续从右往左截取;最后假设 user 为查询实体的一个属性;
  3. 接着处理剩下部分(DepUuid),先判断 user 所对应的类型是否有depUuid属性,如果有,则表示该方法最终是根据 “ Doc.user.depUuid” 的取值进行查询;否则继续按照步骤 2 的规则从右往左截取,最终表示根据 “Doc.user.dep.uuid” 的值进行查询。
  4. 可能会存在一种特殊情况,比如 Doc包含一个 user 的属性,也有一个 userDep 属性,此时会存在混淆。可以明确在属性之间加上 “_” 以显式表达意图,比如 “findByUser_DepUuid()” 或者 “findByUserDep_uuid()”
  5. 还有一些特殊的参数:例如分页或排序的参数:

有的时候,这里提供的查询关键字并不能满足我们的查询需求,这个时候就可以使用 @Query 关键字,来自定义查询 SQL,例如查询Id最大的User:

如果查询有参数的话,参数有两种不同的传递方式:

1.利用下标索引传参,索引参数如下所示,索引值从1开始,查询中 ”?X” 个数需要与方法定义的参数个数相一致,并且顺序也要一致:

2.命名参数(推荐):这种方式可以定义好参数名,赋值时采用@Param(“参数名”),而不用管顺序:

查询时候,也可以是使用原生的SQL查询,如下:

涉及到数据修改操作,可以使用 @Modifying 注解,@Query 与 @Modifying 这两个 annotation一起声明,可定义个性化更新操作,例如涉及某些字段更新时最为常用,示例如下:

  1. 方法的返回值应该是 int,表示更新语句所影响的行数
  2. 在调用的地方必须加事务,没有事务不能正常执行
  3. 默认情况下, Spring Data 的每个方法上有事务, 但都是一个只读事务. 他们不能完成修改操作

说到这里,再来顺便说说Spring Data 中的事务问题:

  1. Spring Data 提供了默认的事务处理方式,即所有的查询均声明为只读事务。
  2. 对于自定义的方法,如需改变 Spring Data 提供的事务默认方式,可以在方法上添加 @Transactional 注解。
  3. 进行多个 Repository 操作时,也应该使它们在同一个事务中处理,按照分层架构的思想,这部分属于业务逻辑层,因此,需要在Service 层实现对多个 Repository 的调用,并在相应的方法上声明事务。
# none:默认值,什么都不做,每次启动项目,不会对数据库进行任何验证和操作 # create:每次运行项目,没有表会新建表,如果表内有数据会被清空 # create-drop:每次程序结束的时候会清空表 # update:每次运行程序,没有表会新建表,但是表内有数据不会被清空,只会更新表结构。 # validate:运行程序会校验数据与数据库的字段类型是否相同,不同会报错

我要回帖

更多关于 每个人都是主角的句子 的文章

 

随机推荐