最近在改造一个spring boot的项目,看到下面代码
package com.example.demo.repository;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository;
import com.example.demo.data.TestEntity;
public interface TTestRepository extends CrudRepository<TestEntity, Long>,JpaSpecificationExecutor<TestEntity>{
TestEntity findByUserName(String userName);
Page<TestEntity> queryByUserName(String userName,Pageable pageable);
Slice<TestEntity> queryById(Long Id,Pageable pageable);
List<TestEntity> findBypassWord(String passWord,Sort sort);
}
注入接口调相应的方法,
@RestController
public class TestInterfaceImpl {
@Autowired
TTestRepository itestRepository;
@RequestMapping("/findById")
public String testRep(){
TestEntity entity = itestRepository.findByUserName("ZhangSan");
return entity.toString();
}
@RequestMapping("/add")
public String testAdd(){
TestEntity entity = new TestEntity("LiSi","123456");
itestRepository.save(entity);
return entity.toString();
}
@RequestMapping("/queryPage")
public String queryPage(@PageableDefault(value=20,sort={"id","userName"},direction = Sort.Direction.DESC) Pageable pageable){
Page<TestEntity> page = itestRepository.queryByUserName("ZhangSan", pageable);
return page.toString();
}
@RequestMapping("/querySlice")
public String querySlice(@PageableDefault(value=20,sort={"id","userName"},direction = Sort.Direction.DESC) Pageable pageable){
Slice<TestEntity> slice = itestRepository.queryById(1l, pageable);
return slice.getContent().get(0).toString();
}
}
正常工作。
看到这百思不得其解,没有找到接口的实现类啊???
1:继承了CrudRepository、JpaSpecificationExecutor接口也没看到自己写的接口类的实现,这是怎么一回事?
答1:了解到spring-data-jpa提供了CrudRepository、JpaSpecificationExecutor接口的默认实现,实现类为SimpleJpaRepository,package:org.springframework.data.jpa.repository.support
/**
* Default implementation of the {@link org.springframework.data.repository.CrudRepository} interface. This will offer* you a more sophisticated interface than the plain {@link EntityManager} .
*
* @author Oliver Gierke
* @author Eberhard Wolff
* @author Thomas Darimont
* @author Mark Paluch
* @param <T> the type of the entity to handle
* @param <ID> the type of the entity's identifier
*/
@Repository
@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID extends Serializable>
implements JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
2:CrudRepository<TestEntity, Long>,JpaSpecificationExecutor<TestEntity>接口中的方法有默认实现,那接口中自定义的方法没写实现类,为什么也能正常工作???
下面译自spring-data官方文档,
定义查询方法
存储库代理有两种方法从方法名派生特定于存储区的查询。它可以直接从方法名派生查询,或者使用手动定义的查询。可用选项取决于实际存储。但是,必须有一种策略来决定创建什么样的实际查询。让我们来看看可用的选项。
直接从方法名派生查询
拿上面的作为例子:
TestEntity findByUserName(String userName);
该机制将前缀分隔为find…By
, read…By
, query…By
, count…By
,get…By
去掉然后开始解析其余部分。
findByUserName去掉前缀则为UserName,该机制开始按照驼峰的命名方式从右往左开始解析,解析为User,Name,Name,解析完成后发现name并不是TestEntity中的属性,于是继续解析为UserName,而userName为TestEntity中的属性,所以生成了from TestEntity where userName=?的query语句。
如果解析到最后也没匹配,则会抛出异常在程序启动的时候。
附TestEntity实体代码:
@Entity
@Table(name = "T_TEST")
public class TestEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "username")
private String userName;
@Column(name = "password")
private String passWord;
@Column(name = "email")
private String email;
@Column(name = "mobile")
private String mobile;
@Column(name = "nickname")
private String nickName;
public TestEntity() {
super();
}
public TestEntity(String userName, String passWord) {
super();
this.userName = userName;
this.passWord = passWord;
}
/**
* @return id
*/
public Long getId() {
return id;
}
/**
* @param id 要设置的 id
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return userName
*/
public String getUserName() {
return userName;
}
/**
* @param userName 要设置的 userName
*/
public void setUserName(String userName) {
this.userName = userName;
}
/**
* @return passWord
*/
public String getPassWord() {
return passWord;
}
/**
* @param passWord 要设置的 passWord
*/
public void setPassWord(String passWord) {
this.passWord = passWord;
}
/**
* @return email
*/
public String getEmail() {
return email;
}
/**
* @param email 要设置的 email
*/
public void setEmail(String email) {
this.email = email;
}
/**
* @return mobile
*/
public String getMobile() {
return mobile;
}
/**
* @param mobile 要设置的 mobile
*/
public void setMobile(String mobile) {
this.mobile = mobile;
}
/**
* @return nickName
*/
public String getNickName() {
return nickName;
}
/**
* @param nickName 要设置的 nickName
*/
public void setNickName(String nickName) {
this.nickName = nickName;
}
@Override
public String toString() {
return "TestEntity [id=" + id + ", userName=" + userName + ", passWord=" + passWord + ", email=" + email + ", mobile=" + mobile + ", nickName=" + nickName + "]";
}
}
完。