JPA全稱Java Persistence API.JPA通過JDK 5.0注解或XML描述對象-關(guān)系表的映射關(guān)系,并將運行期的實體對象持久化到數(shù)據(jù)庫中。
JPA 的目標之一是制定一個可以由很多供應(yīng)商實現(xiàn)的API,并且開發(fā)人員可以編碼來實現(xiàn)該API,而不是使用私有供應(yīng)商特有的API。
JPA是需要Provider來實現(xiàn)其功能的,Hibernate就是JPA Provider中很強的一個,應(yīng)該說無人能出其右。從功能上來說,JPA就是Hibernate功能的一個子集。
本教程大概流程:
- 借助idea實現(xiàn)springboot 和 spring data jpa 整合
- 實現(xiàn)JpaRepository接口快捷開發(fā)
- 自定義Mapper查詢接口方法
- MVC架構(gòu)+分頁功能實戰(zhàn)
- QueryDSL工具與之的整合
首先我的開發(fā)環(huán)境:
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>
<groupId>springboot-jpa</groupId>
<artifactId>springboot-jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot-jpa</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>1.4.5.RELEASE</version>
<scope>test</scope>
</dependency>
<!--querydsl依賴-->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<scope>provided</scope>
</dependency>
<!--阿里巴巴數(shù)據(jù)庫連接池,專為監(jiān)控而生 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.26</version>
</dependency>
<!-- 阿里巴巴fastjson,解析json視圖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.15</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!--添加QueryDSL插件支持-->
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</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;
@Column(nullable = false)
private String username;
@Column(nullable = false)
private Date birthday;
@Column(nullable = false)
private String sex;
@Column(nullable = false)
private String address;
}
@Data注解是 lombok 依賴包下的注解,它可以自動幫我們生成set/getter方法,簡化代碼量。有興趣的可以詳細了解,這里不做多解釋。
4. 實現(xiàn)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);// 參數(shù)username 映射到數(shù)據(jù)庫字段username
}
注意:只有@Query 的注解下不能使用insert,我們需要在上面再添加個@Modify注解,我習(xí)慣都加,nativeQuery 是詢問是否使用原生sql語句。多表查詢也是在這里手寫sql,不做演示。因為后面我們用更好的支持多表查詢的工具框架 QueryDSL來幫助我們更簡潔的實現(xiàn)它。
5.實現(xiàn)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);
/** 查詢?nèi)苛斜?/
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;
}
/**
* 查詢?nèi)苛斜?并做分頁
* @param pageNum 開始頁數(shù)
* @param pageSize 每頁顯示的數(shù)據(jù)條數(shù)
*/
@Override
public Iterator<User> selectAll(int pageNum, int pageSize) {
//將參數(shù)傳給這個方法就可以實現(xiàn)物理分頁了,非常簡單。
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。
當(dāng)然也可以對分頁進行封裝,封裝后的展示。
Page<User> datas = userRepository.findAll(PageableTools.basicPage(1, 5, new SortDto("id")));
是不是很簡潔。大家可以自己嘗試一下。
6. 實現(xiàn)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環(huán)境下如何配置QueryDSL環(huán)境 http://www.itdecent.cn/p/a22447c0897c
- 使用QueryDSL與SpringDataJPA實現(xiàn)單表普通條件查詢 http://www.itdecent.cn/p/4e9d8adaeeb2
- 使用QueryDSL與SpringDataJPA完成Update&Delete http://www.itdecent.cn/p/ac388c3c36c2
- 使用QueryDSL與SpringDataJPA實現(xiàn)多表關(guān)聯(lián)查詢 http://www.itdecent.cn/p/6199e76a5485
注意一點,目前springboot2.0 版本對JPA支持有誤,如果你用springboot2 來配置querydsl,application啟動類會運行不起來,正確的依賴包或者是配置類我還沒有找到,希望有點子的朋友可以和我聯(lián)系。 本人QQ:844072586