本文章参考文档为《SpringDataJpa从入门到精通》
首先, 我觉得入门SpringDataJpa的话, 我们首先要理清楚。 JPA、Hibernate和SpringDataJpa的关系。
全称Java Persistence API,可以通过注解或者XML描述【对象-关系表】之间的映射关系,并将实体对象持久化到数据库中。
但是它只是提供了一种规范, 而Hibernate和SpringDataJpa就是实现了这种规范的ORM框架。
而Sun为什么要引入JPA ORM规范, 因为Sun想要整合ORM技术, 实现天下归一。
(怎么样, 是不是很酷)
其实学习JAVA我觉得就是学习其对应技术的API, 如下是SpringDataJpa涉及到的主要类(接口), 先有个印象。
这是使用idea的F4功能看到了所有继承了Repository接口的类(包括我自定义的类以com.example开头), 其中红框的至关重要, 需要重点学习。
以上的暂时有一个印象就好, 接下来都会就说到。(有一点需要明确, 只要继承了Repository接口, 那么你就算有了SpringDataJpa的能力, 就可以做一些基础的查询了。 如果要是实现了CrudRepository接口, 那么厉害了, 你就可以做增删改查了。 是不是很cool? 记得, 越简单的越NB)
首先, 开发工具推荐idea, 因为构建起一个SpringDataJpa的项目会灰常的快。
然后一路next, 我们得到了一个SpringDataJpa的开发环境。 对了, 别忘记改一下你的配置文件(把你的数据库配置进去)。
然后在数据库中, 推荐学习的时候使用Mysql, 新建一张表, 刚开始简单一点。
新建一张 user 表, 以下是数据结构:
然后自定义一个接口, 继承CrudRepository。
public interface UserRepository extends CrudRepository {}
注意, 我这个接口里面什么都没有写。(泛型中的第一个为一个实体类, 第二个为这个实体类的主键类型, 如果是联合主键这里就是一个XXXKey的类)
新建一个Controller类
/**
* User的控制类
*
* @author YangHang
* @Date 2018/11/28 23:13
*/
@Controller
@RequestMapping(path = "/demo")
public class UserController {
/**
* DAO层操作对象
*/
@Autowired
private UserRepository userRepository;
/**
* 分页DAO层操作对象
*/
@Autowired
private UserPagingAndSortingRepository userPagingAndSortingRepository;
/**
* 添加用户操作
*
* @param name 用户的姓名
* @param email 用户的邮箱
* @return message 操作提示信息
*/
@PostMapping(path = "/addNewUser")
@ResponseBody
public String addNewUser(@RequestParam String name, @RequestParam String email) {
Assert.notNull(name, "NAME MUST BE NOT NULL");
Assert.notNull(email, "EMAIL MUST BE NOT NULL");
User user = new User();
user.setName(name);
user.setEmail(email);
userRepository.save(user);
return "添加用户成功";
}
/**
* 获取所有的用户对象
*
* @return userList 用户
*/
@PostMapping(path = "/getAllUser")
@ResponseBody
public List getAllUser() {
Iterable userIterable = userRepository.findAll();
List userList = new ArrayList<>();
if (userIterable != null) {
userIterable.forEach(user -> userList.add(user));
}
return userList;
}
/**
* 根据用户名称查询所有用户
*
* @param name 用户名称
* @return userList 用户
*/
@PostMapping(path = "/queryUserListByName")
@ResponseBody
public List queryUserListByName(@RequestParam String name) {
Assert.notNull(name, "NAME MUST BE NOT NULL");
List userList = userRepository.findByName(name);
return userList;
}
/**
* 根据用户名称和邮箱查询所有用户
*
* @param name 用户名称
* @param email 用户邮箱
* @return userList 用户
*/
@PostMapping(path = "/queryUserListByNameAndEmail")
@ResponseBody
public List queryUserListByNameAndEmail(@RequestParam String name, @RequestParam String email) {
Assert.notNull(name, "NAME MUST BE NOT NULL");
Assert.notNull(email, "EMAIL MUST BE NOT NULL");
List userList = userRepository.findByNameAndEmail(name, email);
return userList;
}
/**
* 根据用户id删除
*
* @param id 用户主键
*/
@PostMapping("/deleteById")
@ResponseBody
public String deleteById(@RequestParam Long id) {
Assert.notNull(id, "ID MUST BE NOT NULL");
userRepository.deleteById(id);
return "删除对象成功";
}
/**
* 验证分页并排序的方法
*
* @param page 页码
* @param size 每页的条数
* @return userPage 分页之后的对象集合
*/
@PostMapping("/queryUserPage")
@ResponseBody
public Page getAllUserByPage(@RequestParam int page,@RequestParam int size) {
return userPagingAndSortingRepository.findAll(PageRequest.of(page, size, new Sort(Sort.Direction.ASC, "name")));
}
}
我这里的方法比较多, 刚开始接触SpringDataJpa的小伙伴只需要看userRepository的方法即可。
最后呢, 启动项目, 使用POSTMAN调一下下, 你就会发现, 你已经会用SpringDataJpa进行编码了。
相信聪明的小伙伴已经知道了, 之所以叫CrudRepository, 就是默认帮你实现了增删改查的底层类嘛。
SpringDataJpa最简单的分页实现就是继承JPA大家族的PagingAndSortingRepository接口。
我们可以点开源码开一下。
这个接口里面只提供了两个方法, 入参分别是Sort对象和Pageable接口。
我们可以看到Sort是一个类, 我们可以直接传入这个类的对象来实现排序。
主要是Pageable接口, 想要完成分页, 需要传入一个这个接口的实现, 点击F4看一下这个接口的层次, 我们会发现PageRequest这个类, 通过它的of() 方法我们可以构建出这个接口的实现类,看一下源码。
public class PageRequest extends AbstractPageRequest {
private static final long serialVersionUID = -4541509938956089562L;
private final Sort sort;
/** @deprecated */
@Deprecated
public PageRequest(int page, int size) {
this(page, size, Sort.unsorted());
}
/** @deprecated */
@Deprecated
public PageRequest(int page, int size, Direction direction, String... properties) {
this(page, size, Sort.by(direction, properties));
}
/** @deprecated */
@Deprecated
public PageRequest(int page, int size, Sort sort) {
super(page, size);
this.sort = sort;
}
public static PageRequest of(int page, int size) {
return of(page, size, Sort.unsorted());
}
public static PageRequest of(int page, int size, Sort sort) {
return new PageRequest(page, size, sort);
}
public static PageRequest of(int page, int size, Direction direction, String... properties) {
return of(page, size, Sort.by(direction, properties));
}
public Sort getSort() {
return this.sort;
}
public Pageable next() {
return new PageRequest(this.getPageNumber() + 1, this.getPageSize(), this.getSort());
}
public PageRequest previous() {
return this.getPageNumber() == 0?this:new PageRequest(this.getPageNumber() - 1, this.getPageSize(), this.getSort());
}
public Pageable first() {
return new PageRequest(0, this.getPageSize(), this.getSort());
}
public boolean equals(@Nullable Object obj) {
if(this == obj) {
return true;
} else if(!(obj instanceof PageRequest)) {
return false;
} else {
PageRequest that = (PageRequest)obj;
return super.equals(that) && this.sort.equals(that.sort);
}
}
public int hashCode() {
return 31 * super.hashCode() + this.sort.hashCode();
}
public String toString() {
return String.format("Page request [number: %d, size %d, sort: %s]", new Object[]{Integer.valueOf(this.getPageNumber()), Integer.valueOf(this.getPageSize()), this.sort});
}
}
主要有两个构造函数, 一个是PageRequest(int page, int size)
其中page是第几页(从0开使), size是一页多少条记录
另外一个构造是PageRequest(int page, int size, Sort sort)
多了一个排序的对象, 即可以按固定的排序来分页。
具体的代码?有实例, 即用userPagingAndSortingRepository实现的。
我叫杨小邪, 如果有问题, 请留言讨论哈。 我下一篇会将一下SpringDataJpa的定义式查询方法和注解式查询方法, 希望大家喜欢。