JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
JPA 的目标之一是制定一个可以由很多供应商实现的API,并且开发人员可以编码来实现该API,而不是使用私有供应商特有的API。
JPA是需要Provider来实现其功能的,Hibernate就是JPA Provider中很强的一个,应该说无人能出其右。从功能上来说,JPA就是Hibernate功能的一个子集。
本教程大概流程:
- 借助idea实现springboot 和 spring data jpa 整合
- 实现JpaRepository接口快捷开发
- 自定义Mapper查询接口方法
- MVC架构+分页功能实战
- QueryDSL工具与之的整合
首先我的开发环境:
jdk1.8+maven3+IDEA
1. 完善pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>springboot-jpa<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>springboot-jpa<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">version</span>></span>0.0.1-SNAPSHOT<span class="hljs-tag"></<span class="hljs-name">version</span>></span>
<span class="hljs-tag"><<span class="hljs-name">packaging</span>></span>jar<span class="hljs-tag"></<span class="hljs-name">packaging</span>></span>
<span class="hljs-tag"><<span class="hljs-name">name</span>></span>springboot-jpa<span class="hljs-tag"></<span class="hljs-name">name</span>></span>
<span class="hljs-tag"><<span class="hljs-name">description</span>></span>Demo project for Spring Boot<span class="hljs-tag"></<span class="hljs-name">description</span>></span>
<span class="hljs-tag"><<span class="hljs-name">parent</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.springframework.boot<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>spring-boot-starter-parent<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">version</span>></span>2.0.0.RELEASE<span class="hljs-tag"></<span class="hljs-name">version</span>></span>
<span class="hljs-tag"><<span class="hljs-name">relativePath</span>/></span> <span class="hljs-comment"><!-- lookup parent from repository --></span>
<span class="hljs-tag"></<span class="hljs-name">parent</span>></span>
<span class="hljs-tag"><<span class="hljs-name">properties</span>></span>
<span class="hljs-tag"><<span class="hljs-name">project.build.sourceEncoding</span>></span>UTF-8<span class="hljs-tag"></<span class="hljs-name">project.build.sourceEncoding</span>></span>
<span class="hljs-tag"><<span class="hljs-name">project.reporting.outputEncoding</span>></span>UTF-8<span class="hljs-tag"></<span class="hljs-name">project.reporting.outputEncoding</span>></span>
<span class="hljs-tag"><<span class="hljs-name">java.version</span>></span>1.8<span class="hljs-tag"></<span class="hljs-name">java.version</span>></span>
<span class="hljs-tag"></<span class="hljs-name">properties</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dependencies</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.springframework.boot<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>spring-boot-starter<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.springframework.boot<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>spring-boot-starter-test<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.springframework.boot<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>spring-boot-starter-web<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>mysql<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>mysql-connector-java<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.springframework.boot<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>spring-boot-starter-data-jpa<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.projectlombok<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>lombok<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">version</span>></span>1.16.18<span class="hljs-tag"></<span class="hljs-name">version</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.springframework.boot<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>spring-boot-test<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">version</span>></span>1.4.5.RELEASE<span class="hljs-tag"></<span class="hljs-name">version</span>></span>
<span class="hljs-tag"><<span class="hljs-name">scope</span>></span>test<span class="hljs-tag"></<span class="hljs-name">scope</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span>
<span class="hljs-comment"><!--querydsl依赖--></span>
<span class="hljs-tag"><<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>com.querydsl<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>querydsl-jpa<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>com.querydsl<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>querydsl-apt<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">scope</span>></span>provided<span class="hljs-tag"></<span class="hljs-name">scope</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span>
<span class="hljs-comment"><!--阿里巴巴数据库连接池,专为监控而生 --></span>
<span class="hljs-tag"><<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>com.alibaba<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>druid<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">version</span>></span>1.0.26<span class="hljs-tag"></<span class="hljs-name">version</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span>
<span class="hljs-comment"><!-- 阿里巴巴fastjson,解析json视图 --></span>
<span class="hljs-tag"><<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>com.alibaba<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>fastjson<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">version</span>></span>1.2.15<span class="hljs-tag"></<span class="hljs-name">version</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>com.alibaba<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>druid<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">version</span>></span>1.1.3<span class="hljs-tag"></<span class="hljs-name">version</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependencies</span>></span>
<span class="hljs-tag"><<span class="hljs-name">build</span>></span>
<span class="hljs-tag"><<span class="hljs-name">plugins</span>></span>
<span class="hljs-tag"><<span class="hljs-name">plugin</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.springframework.boot<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>spring-boot-maven-plugin<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"></<span class="hljs-name">plugin</span>></span>
<span class="hljs-comment"><!--添加QueryDSL插件支持--></span>
<span class="hljs-tag"><<span class="hljs-name">plugin</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>com.mysema.maven<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>apt-maven-plugin<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">version</span>></span>1.1.3<span class="hljs-tag"></<span class="hljs-name">version</span>></span>
<span class="hljs-tag"><<span class="hljs-name">executions</span>></span>
<span class="hljs-tag"><<span class="hljs-name">execution</span>></span>
<span class="hljs-tag"><<span class="hljs-name">configuration</span>></span>
<span class="hljs-tag"><<span class="hljs-name">outputDirectory</span>></span>target/generated-sources/java<span class="hljs-tag"></<span class="hljs-name">outputDirectory</span>></span>
<span class="hljs-tag"><<span class="hljs-name">processor</span>></span>com.querydsl.apt.jpa.JPAAnnotationProcessor<span class="hljs-tag"></<span class="hljs-name">processor</span>></span>
<span class="hljs-tag"></<span class="hljs-name">configuration</span>></span>
<span class="hljs-tag"></<span class="hljs-name">execution</span>></span>
<span class="hljs-tag"></<span class="hljs-name">executions</span>></span>
<span class="hljs-tag"></<span class="hljs-name">plugin</span>></span>
<span class="hljs-tag"></<span class="hljs-name">plugins</span>></span>
<span class="hljs-tag"></<span class="hljs-name">build</span>></span>
</project>
2. 完善application.properties 文件
spring.datasource.url=jdbc:mysql://localhost:3306/user
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type: com.alibaba.druid.pool.DruidDataSource
spring.datasource.filters:stat
spring.datasource.maxActive: 20
spring.datasource.initialSize: 1
spring.datasource.maxWait: 60000
spring.datasource.minIdle: 1
spring.datasource.timeBetweenEvictionRunsMillis: 60000
spring.datasource.minEvictableIdleTimeMillis: 300000
spring.datasource.validationQuery: select 'x'
spring.datasource.testWhileIdle: true
spring.datasource.testOnBorrow: false
spring.datasource.testOnReturn: false
spring.datasource.poolPreparedStatements: true
spring.datasource.maxOpenPreparedStatements: 20
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.show-sql=true
3. 编写实体类 User.java
package com.fantj.model;
import lombok.Data;
import javax.persistence.*;
import java.util.Date;
@Data
@Entity
@Table(name = "user")
public class User {
public User(){
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
<span class="hljs-meta">@Column</span>(nullable = <span class="hljs-keyword">false</span>)
<span class="hljs-keyword">private</span> String username;
<span class="hljs-meta">@Column</span>(nullable = <span class="hljs-keyword">false</span>)
<span class="hljs-keyword">private</span> Date birthday;
<span class="hljs-meta">@Column</span>(nullable = <span class="hljs-keyword">false</span>)
<span class="hljs-keyword">private</span> String sex;
<span class="hljs-meta">@Column</span>(nullable = <span class="hljs-keyword">false</span>)
<span class="hljs-keyword">private</span> String address;
}
@Data注解是 lombok 依赖包下的注解,它可以自动帮我们生成set/getter方法,简化代码量。有兴趣的可以详细了解,这里不做多解释。
4. 实现DAO层
package com.fantj.repostory;
/**
-
Created by Fant.J.
*/
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
//自定义repository。手写sql
@Query(value = "update user set name=?1 where id=?4",nativeQuery = true) //占位符传值形式
@Modifying
int updateById(String name,int id);
@Query("from User u where u.username=:username") //SPEL表达式
User findUser(@Param("username") String username);// 参数username 映射到数据库字段username
}
注意:只有@Query 的注解下不能使用insert,我们需要在上面再添加个@Modify注解,我习惯都加,nativeQuery 是询问是否使用原生sql语句。多表查询也是在这里手写sql,不做演示。因为后面我们用更好的支持多表查询的工具框架 QueryDSL来帮助我们更简洁的实现它。
5.实现Service层
UserService .java
package com.fantj.service;
/**
- Created by Fant.J.
/
public interface UserService {
/* 删除 /
public void delete(int id);
/* 增加/
public void insert(User user);
/** 更新/
public int update(User user);
/** 查询单个/
public User selectById(int id);
/** 查询全部列表/
public Iterator<User> selectAll(int pageNum, int pageSize);
}
UserServiceImpl.java
package com.fantj.service.impl;
/**
-
Created by Fant.J.
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
/**
- 删除
- @param id
*/
@Override
public void delete(int id) {
userRepository.deleteById(id);
}
/**
- 增加
- @param user
*/
@Override
public void insert(User user) {
userRepository.save(user);
}
/**
- 更新
- @param user
*/
@Override
public int update(User user) {
userRepository.save(user);
return 1;
}
/**
- 查询单个
- @param id
*/
@Override
public User selectById(int id) {
Optional<User> optional = userRepository.findById(id);
User user = optional.get();
return user;
}
/**
- 查询全部列表,并做分页
- @param pageNum 开始页数
- @param pageSize 每页显示的数据条数
*/
@Override
public Iterator<User> selectAll(int pageNum, int pageSize) {
//将参数传给这个方法就可以实现物理分页了,非常简单。
Sort sort = new Sort(Sort.Direction.DESC, "id");
Pageable pageable = new PageRequest(pageNum, pageSize, sort);
Page<User> users = userRepository.findAll(pageable);
Iterator<User> userIterator = users.iterator();
return userIterator;
}
}
分页不止可以这样做,也可以在Controller层进行实例化和初始化然后将Pageable对象传给Service。
当然也可以对分页进行封装,封装后的展示。
Page<User> datas = userRepository.findAll(PageableTools.basicPage(1, 5, new SortDto("id")));
是不是很简洁。大家可以自己尝试一下。
6. 实现Controller
package com.fantj.controller;
/**
-
Created by Fant.J.
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(method = RequestMethod.GET,value = "/delete/{id}")
public void delete(@PathVariable("id")int id){
userService.delete(id);
}
@RequestMapping(method = RequestMethod.POST,value = "/insert")
public void insert(User user){
userService.insert(user);
}
@RequestMapping(method = RequestMethod.POST,value = "/update/{id}")
public void update(@RequestParam User user){
userService.update(user);
}
@RequestMapping(method = RequestMethod.GET,value = "/{id}/select")
public User select(@PathVariable("id")int id){
return userService.selectById(id);
}
@RequestMapping(method = RequestMethod.GET,value = "/selectAll/{pageNum}/{pageSize}")
public List<User> selectAll(@PathVariable("pageNum") int pageNum, @PathVariable("pageSize") int pageSize){
Iterator<User> userIterator = userService.selectAll(pageNum, pageSize);
List<User> list = new ArrayList<>();
while(userIterator.hasNext()){
list.add(userIterator.next());
}
return list;
}
}
QueryDSL工具与上文的整合
可以参考恒宇少年的四篇文章:
- Maven环境下如何配置QueryDSL环境 https://www.jianshu.com/p/a22447c0897c
- 使用QueryDSL与SpringDataJPA实现单表普通条件查询 https://www.jianshu.com/p/4e9d8adaeeb2
- 使用QueryDSL与SpringDataJPA完成Update&Delete https://www.jianshu.com/p/ac388c3c36c2
- 使用QueryDSL与SpringDataJPA实现多表关联查询 https://www.jianshu.com/p/6199e76a5485
注意一点,目前springboot2.0 版本对JPA支持有误,如果你用springboot2 来配置querydsl,application启动类会运行不起来,正确的依赖包或者是配置类我还没有找到,希望有点子的朋友可以和我联系。 本人QQ:844072586
</div>