什么是JPA?
JPA顾名思义就是Java Persistence API的意思,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
使用spring jpa,几乎不需要写数据库操作的代码即可实现基本的CRUD功能;
另外也可以使用Page、Pageable接口和Sort类完成分页排序,十分方便。
本文代码已上传至github,有需要的朋友可以下载:https://github.com/wqwyes/springboot-jpa.git
下面来详细介绍;
创建springboot项目
添加依赖
介绍一下:
Spring JPA依赖是必须的,
starter-web项目中会用到;
junit是我在单元测试时用到的;
devtools依赖用于热部署
<!--SpringMVC依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--Spring JPA依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional><!-- optional=true,依赖不会传递,该项目依赖devtools;之后依赖myboot项目的项目如果想要使用devtools,需要重新引入 -->
<scope>true</scope>
</dependency>
配置文件application.yml
注意配置文件的写法,一不小心就会出错,比如之前我遇到的问题,虽然很小但是却花费我很长时间:
springboot进行junit测试出现:Failed to configure a DataSource问题;包括":"后有空格
spring:
datasource:
url: jdbc:mysql://localhost:3307/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai
username: root
password: root
driverClassName: com.mysql.jdbc.Driver
#jpa 测试
jpa:
hibernate:
ddl-auto: update # 新增数据库链接必须的参数
# 控制台显示SQL
show-sql: true
properties:
hibernate.format_sql: true
看下数据库内容:
编写实体类User
注意@Id导入的类是javax.persistence,导入其他的会报错
注解解释
@Entity:声明类为实体或表
@Table:声明表名
@Id:指定的类的属性,用于识别(一个表中的主键)
@GeneratedValue:提供了主键的生成策略
import javax.persistence.*;
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String old;
}
编写UserRepository类,只需继承JpaRepository即可
import com.wqw.springbootjpa.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User,Integer> {
}
编写UserService及其实现类UserServiceImp
UserService类
public interface UserService {
//根据信息搜索用户
List<User> getAllByOther(Example example);
// 普通分页
Page<User> getPage(Integer pageNum, Integer pageLimit);
// 排序分页
Page<User> getPageSort(Integer pageNum, Integer pageLimit);
//保存用户
void savaUser(User user);
}
UserServiceImp类
@Service
public class UserServiceImp implements UserService {
@Autowired
UserRepository userRepository;
@Override
public List<User> getAllByOther(Example example) {
List<User> users = userRepository.findAll(example);
return users;
}
@Override
public Page<User> getPage(Integer pageNum, Integer pageLimit) {
Pageable pageable =new PageRequest(pageNum - 1,pageLimit);
return userRepository.findAll(pageable);
}
@Override
public Page<User> getPageSort(Integer pageNum, Integer pageLimit) {
Sort sort = new Sort(Sort.Direction.DESC,"old");
Pageable pageable =new PageRequest(pageNum - 1, pageLimit, sort);
return userRepository.findAll(pageable);
}
@Override
public void savaUser(User user) {
userRepository.save(user);
}
}
编写UserController类
编写UserController类
@RestController
public class UserController {
@Autowired
private UserService userService;
//搜索用户 /findUser?name=test
@GetMapping("/findUser")
public List<User> findUser(@RequestParam(value = "name")String name){
System.out.println("name="+name);
User user = new User();
user.setName(name);
Example<User> example =Example.of(user);
return userService.getAllByOther(example);
}
// 分页显示数据
@GetMapping("/user")
public Page<User> showPage(@RequestParam(value = "page") Integer page, @RequestParam(value = "size") Integer size){
System.out.println("分页: page:"+page+"; size:"+size);
return userService.getPage(page, size);
}
// 排序分页显示数据
@GetMapping("/user_sort")
public Page<User> showSortPage(@RequestParam(value = "page") Integer page, @RequestParam(value = "size") Integer size){
System.out.println("排序分页: page:"+page+"; size:"+size);
return userService.getPageSort(page, size);
}
//保存用户
@PostMapping("/saveUser")
public String saveUser(@RequestBody User user){
userService.savaUser(user);
return "保存成功!";
}
}
使用自己编写方法实现CRUD
比如在UserRepository类中添加方法:
public interface UserRepository extends JpaRepository<User,Integer> {
//自己定义方法实现查询
List<User> findByNameLike(String name);
}
无需对实现UserRepository类,在controller中添加:
@Autowired
UserRepository userRepository;
//自定义方法:通过name关键字查找用户
@GetMapping("/findUserByNameLike")
public List<User> findByNameLike(@RequestParam(value = "name") String name){
return userRepository.findByNameLike(name);
}
即可实现SQL 中的 "like"方法,异常简便。
这是因为 jpa 通过关键字以及驼峰命名解析,findByName 会帮你解析成select from user where name like ?,从而实现查询.
其余更详细方法可参考:
SpringBoot JPA实现增删改查、分页、排序、事务操作等功能_林老师带你学编程的博客-CSDN博客_jpa springboot 增删改查
自定义SQL查询
如果我们想通过自定义的SQL查询也是支持的。
通过@Query注解实现SQL查询;
如涉及到删除和修改在需要加上@Modifying,同时也要加上@Transactional,否则会报如下错误:
org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query
下面通过实例介绍
在UserRepository定义方法:
//自定义SQL,删除指定user
@Transactional(timeout = 10)
@Modifying
@Query("delete from User where id = ?1")
void deleteUserById(Integer id);
//自定义SQL,修改userName
@Transactional(timeout = 10)
@Modifying
@Query("update User u set u.name= ?1 where u.id= ?2")
Integer modifyByUserId(String userName,Integer id);
//自定义SQL,根据名字查询
@Query("SELECT u from User u where u.name= ?1")
List<User> getUserByName(String name);
注:
1、@Query里sql语句,User代表的是实体类,并不是表名;
2、 “?1” 与 “?2” 对应方法中的两个参数
继续实现service、controller即可,这里不做分析。