JapRepository和CruRepository以及jpa方法
前言
Github:https://github.com/HealerJean
用了这么久springboot springdata jpa了,是时候简单总结一下下了
1、CrudRepository与JpaRepository的不同
其实用起来一模一样
1.1、继承关系
PagingAndSortingRepository 继承 CrudRepository,JpaRepository 继承 PagingAndSortingRepository,所以,我们以后一般用JpaRepository
12、使用关系
CrudRepository 提供基本的增删改查;
PagingAndSortingRepository 提供分页和排序方法;
JpaRepository 提供JPA需要的方法。
2、方法集锦
关键字 | 方法命名 | sql where字句 |
And | findByNameAndPwd | where name= ? and pwd =? |
Or | findByNameOrSex | where name= ? or sex=? |
Is,Equals | findById,findByIdEquals | where id= ? |
Between | findByIdBetween | where id between ? and ? |
LessThan | findByIdLessThan | where id < ? |
LessThanEquals | findByIdLessThanEquals | where id <= ? |
GreaterThan | findByIdGreaterThan | where id > ? |
GreaterThanEquals | findByIdGreaterThanEquals | where id > = ? |
After | findByIdAfter | where id > ? |
Before | findByIdBefore | where id < ? |
IsNull | findByNameIsNull | where name is null |
isNotNull,NotNull | findByNameNotNull | where name is not null |
Like | findByNameLike | where name like ? |
NotLike | findByNameNotLike | where name not like ? |
StartingWith |
findByNameStartingWith | where name like '?%' |
EndingWith | findByNameEndingWith | where name like '%?' |
Containing | findByNameContaining | where name like '%?%' |
OrderBy | findByIdOrderByXDesc | where id=? order by x desc |
Not | findByNameNot | where name <> ? |
In | findByIdIn(Collection<?> c) | where id in (?) |
NotIn | findByIdNotIn(Collection<?> c) | where id not in (?) |
True |
findByAaaTue |
where aaa = true |
False | findByAaaFalse | where aaa = false |
IgnoreCase | findByNameIgnoreCase | where UPPER(name)=UPPER(?) |
2.1、count
count | sql | 解释 |
---|---|---|
1 | Long countByName(String name); | 通过名字查询 |
2 | Long countAllByName(String name); | 通过名字查询 |
3 | Long countBy(); | 查询库中所有的 |
4 | long count(); | 查询库中所有的,注意这里为long |
2.1.2、测试
public interface DemoEntityJapCruRepository extends JpaRepository<DemoEntity,Long> {
Long countByName(String name);
Long countAllByName(String name);
Long countBy();
long count();
}
2.2、exists 检测数据是否存在
exists | sql | 解释 |
---|---|---|
1 | boolean exists(Long id); | 判断id的实体是否存在 |
3 | boolean existsByUserInfoId(Long userInfoId); | 判断库里面的匹配项是否存在 |
boolean exists(Long id);
boolean existsByUserInfoId(Long userInfoId);
2.3、返回结果为对象
2.3.1、返回Date类型
@Query("select d.cdate from DemoEntity d where d.id = :id")
Date findDate(@Param("id") Long id);
2.3.2、返回实体对象
下面这种方式不可以使用原生的sql语句,必须使用Hibernate 对象语法。所以尽量使用mybatis
@Query("select new com.hlj.data.res.RspDemoModel(d.id,d.name,d.age) from DemoEntity d where d.id = :id")
RspDemoModel findDtoModel(@Param("id") Long id) ;
3、getOne和上面的findOne区别
使用中get和上面的find在Jpa方法中没什么区别的,比如:getByNameContaining也就是说可以用下吗的get去替代上面的find
但是如果是getOne和findOne就会有一些问题
findOne()是返回的是一个实体对象,查不到的时候会返回null。 getOne()是返回的一个对象的引用,也是是代理对象,查不到会抛异常。SpringBoot版本1.5.4
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
3.1、测试Repository
public interface DemoEntityJapRepository extends JpaRepository<DemoEntity,Long> {
}
public interface DemoEntityCruRepository extends CrudRepository<DemoEntity,Long> {
}
3.2、service
接口
DemoEntity findOrGet (String type , String which , Long id);
实现类
@Override
public DemoEntity findOrGet(String type , String which , Long id) {
DemoEntity demoEntitie = null ;
if(StringUtils.equals("jpa", type)){
if(StringUtils.equals("find",which )){
demoEntitie = demoEntityJapRepository.findOne(id) ;
}else if(StringUtils.equals("get",which )){
demoEntitie = demoEntityJapRepository.getOne(id) ;
}
}else if(StringUtils.equals("cru",type )){
if(StringUtils.equals("find",which )){
demoEntitie = ( demoEntityCruRepository.findOne(id));
}else if(StringUtils.equals("get",which )){
//下面这种不存在的
// demoEntitie = demoEntityCruRepository.getOne(id);
}
}
System.out.println(demoEntitie);
return demoEntitie ; //jpa getOne(代理对象能够获取结果但是不能传递到前台)
}
3.3、controller
//http://localhost:8080/demo/jpa/findOrGet?type=jpa&which=get&id=17
@ApiOperation(notes = "所有Demo实体类",
value = "所有Demo实体类",
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE,
response = DemoEntity.class)
@ApiImplicitParams({
@ApiImplicitParam(name = "type",value = "jpa cru",required = true,dataType = "string",paramType = "query")
})
@GetMapping("findOrGet")
@ResponseBody
public ResponseBean findOrGet(String type,String which, Long id){
try {
return ResponseBean.buildSuccess(demo02JapMethodService.findOrGet(type,which,id));
}catch (AppException e){
ExceptionLogUtils.log(e,this.getClass() );
return ResponseBean.buildFailure(e.getCode(),e.getMessage());
}catch (Exception e){
ExceptionLogUtils.log(e,this.getClass() );
return ResponseBean.buildFailure(e.getMessage());
}
}
3.3、测试
3.3.1、测试1 getOne查询一个不存在的数据
http://localhost:8080/demo/jpa/findOrGet?type=cru&which=get&id=100
报错信息
报错的文件是:EntityManagerFactoryBuilderImpl.java报错方法是:handleEntityNotFound报错的行是:144报错的信息是:Unable to find com.hlj.entity.db.demo.DemoEntity with id 100
3.3.2、findOne:查询一个不存在的id数据时,返回的值是null.
type分别为jpa和cur
http://localhost:8080/demo/jpa/findOrGet?type=cru&which=find&id=100
http://localhost:8080/demo/jpa/findOrGet?type=jpa&which=find&id=100
{
"success": true,
"result": null,
"message": "",
"code": "200",
"date": "1547197480777"
}
3.3.3、getOne返回一个存在的数据,也会出现问题
方法中可以使用,再包装之后传递给前端会报错。错误如下
打印日志:DemoEntity(id=17, name=HealerJean, age=2, cdate=2019-01-10 15:15:10.0, udate=2019-01-10 01:15:11.0)
报错信息:
2019-01-11 17:06:47.898 [http-nio-8080-exec-7] ERROR c.h.config.ControllerExceptionConfig - 报错的文件是:AbstractJackson2HttpMessageConverter.java报错方法是:writeInternal报错的行是:299报错的信息是:Could not write JSON: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.hlj.data.general.ResponseBean["result"]->com.hlj.entity.db.demo.DemoEntity_$$_jvstcc7_0["handler"])
原因: Jason转换失败(直接返回前端会造成),不是没有 implements Serializable 的原因
解决方法: //实体类上忽略下面的字段,在Json传递的时候 @JsonIgnoreProperties(value={“hibernateLazyInitializer”,”handler”,”fieldHandler”})
3.4、总结:
总之以后我们使用的时候,就用findOne,不要使用getOne,查询语句get,find不受影响,随意使用
getOne:查询一个不存在的id数据时,直接抛出异常,因为它返回的是一个引用,简单点说就是一个代理对象。
这样一看想起来hibernate中get和load区别