目录
一,概述
Spring JPA通过为用户统一创建和销毁EntityManager,进行事务管理,简化JPA的配置等使用户的开发更加简便。
Spring Data JPA是在Spring JPA的基础上,对持久层做了简化。用户只需声明持久层的接口,不需要实现该接口。Spring Data
JPA内部会根据不同的策略、通过不同的方法创建Query操作数据库。
二、入门demo
user实体类
实体类中常用注解:
- @Entity :声明这个类是一个实体类
- @Table:指定映射到数据库的表格
- @Id :映射到数据库表的主键属性,一个实体只能有一个属性被映射为主键
- @GeneratedValue:主键的生成策略
- @Column配置单列属性
@Entity // 实体
public class User implements Serializable{
private static final long serialVersionUID = 1L;
@Id // 主键
@GeneratedValue(strategy=GenerationType.IDENTITY) // 自增长策略
private Long id; // 用户的唯一标识
@Column(nullable = false) // 映射为字段,值不能为空
private String name;
@Column(nullable = false)
private Integer age;
protected User() { // JPA 的规范要求无参构造函数;设为 protected 防止直接使用
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return String.format(
"User[id=%d, name='%s', age='%d']",
id, name, age);
}
}
Repository接口
- Repository: 最顶层的接口,是一个空接口,目的是为了统一所有的Repository的类型,且能让组件扫描时自动识别
- CrudRepository: Repository的子接口,提供CRUD 的功能。
- PagingAndSortingRepository:CrudRepository的子接口, 添加分页排序。
- JpaRepository: PagingAndSortingRepository的子接口,增加批量操作等。
- JpaSpecificationExecutor: 用来做复杂查询的接口
由图来看,一般使用JpaRepository这个接口做查询即可.这个接口拥有如下方法:
- delete删除或批量删除
- findOne查找单个
- findAll查找所有
- save保存单个或批量保存
- saveAndFlush保存并刷新到数据库
UserRepository :直接或间接继承Repository即可,这里不需要写任何实现
/**
* 用户仓库.
*
*/
public interface UserRepository extends CrudRepository<User, Long>{
}
UserController
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserRepository userRepository;
/**
* 从 用户存储库 获取用户列表
* @return
*/
private List<User> getUserlist() {
List<User> users = new ArrayList<>();
for (User user : userRepository.findAll()) {
users.add(user);
}
return users;
}
/**
* 查询所用用户
* @return
*/
@GetMapping
public ModelAndView list(Model model) {
model.addAttribute("userList", getUserlist());
model.addAttribute("title", "用户管理");
return new ModelAndView("users/list", "userModel", model);
}
/**
* 根据id查询用户
* @param message
* @return
*/
@GetMapping("{id}")
public ModelAndView view(@PathVariable("id") Long id, Model model) {
User user = userRepository.findOne(id);
model.addAttribute("user", user);
model.addAttribute("title", "查看用户");
return new ModelAndView("users/view", "userModel", model);
}
/**
* 获取 form 表单页面
* @param user
* @return
*/
@GetMapping("/form")
public ModelAndView createForm(Model model) {
model.addAttribute("user", new User(null, null));
model.addAttribute("title", "创建用户");
return new ModelAndView("users/form", "userModel", model);
}
/**
* 新建用户
* @param user
* @param result
* @param redirect
* @return
*/
@PostMapping
public ModelAndView create(User user) {
userRepository.save(user);
return new ModelAndView("redirect:/users");
}
/**
* 删除用户
* @param id
* @return
*/
@GetMapping(value = "delete/{id}")
public ModelAndView delete(@PathVariable("id") Long id, Model model) {
userRepository.delete(id);
model.addAttribute("userList", getUserlist());
model.addAttribute("title", "删除用户");
return new ModelAndView("users/list", "userModel", model);
}
/**
* 修改用户
* @param user
* @return
*/
@GetMapping(value = "modify/{id}")
public ModelAndView modifyForm(@PathVariable("id") Long id, Model model) {
User user = userRepository.findOne(id);
model.addAttribute("user", user);
model.addAttribute("title", "修改用户");
return new ModelAndView("users/form", "userModel", model);
}
}
前端页面
首页 list.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> <!--引入thymeleaf名称空间 -->
<head>
<title th:text="${userModel.title}">welcome</title>
</head>
<body>
<!-- 引入header -->
<div th:replace="~{fragments/header :: header}">...</div>
<h3 th:text="${userModel.title}">Welcome</h3>
<div>
<a href="/users/form.html">创建用户</a>
</div>
<table border="1">
<thead>
<tr>
<td>ID</td>
<td>Age</td>
<td>Name</td>
</tr>
</thead>
<tbody>
<tr th:if="${userModel.userList.size()} eq 0">
<td colspan="3">没有用户信息!!</td>
</tr>
<tr th:each="user : ${userModel.userList}"> <!--遍历-->
<td th:text="${user.id}">1</td>
<td th:text="${user.age}">11</td>
<td><a href="view.html" th:href="@{'/users/' + ${user.id}}"
th:text="${user.name}">mmall</a></td>
</tr>
</tbody>
</table>
<div th:replace="~{fragments/footer :: footer}">...</div>
</body>
</html>
详情页 view.html
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<title th:text="${userModel.title}">users : View</title>
</head>
<body>
<div th:replace="~{fragments/header :: header}">...</div>
<h3 th:text="${userModel.title}">Welcome</h3>
<div>
<a href="/users">返回主页</a>
</div>
<div>
<p><strong>ID:</strong><span id="id" th:text="${userModel.user.id}">123</span></p>
<p><strong>Name:</strong><span id="name" th:text="${userModel.user.name}">mmall</span></p>
<p><strong>Age:</strong><span id="age" th:text="${userModel.user.age}">30</span></p>
</div>
<div>
<a th:href="@{'/users/delete/' + ${userModel.user.id}}">删除 </a>
| <a th:href="@{'/users/modify/' + ${userModel.user.id}}">修改</a>
</div>
<div th:replace="~{fragments/footer :: footer}">...</div>
</body>
</html>
修改新增页面 form.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<title th:text="${userModel.title}">users : View</title>
</head>
<body>
<div th:replace="~{fragments/header :: header}">...</div>
<h3 th:text="${userModel.title}">Welcome</h3>
<div>
<a href="/users">返回主页</a>
</div>
<!-- form表单绑定对象属性,1、直接 th:value= ${userModel.user.id}
2、 th:value="*{name}" 配合 th:object="${userModel.user}" 使用 -->
<form action="/users" method="POST" th:object="${userModel.user}">
<input type="hidden" name="id" th:value="*{id}">
名称:<br>
<input type="text" name="name" th:value="*{name}">
<br>
年龄:<br>
<input type="text" name="age" th:value="*{age}">
<input type="submit" value="提交">
</form>
<div th:replace="~{fragments/footer :: footer}">...</div>
</body>
</html>
build.gradle
// buildscript 代码块中脚本优先执行
buildscript {
// ext 用于定义动态属性
ext {
springBootVersion = '1.5.2.RELEASE'
}
// 自定义 Thymeleaf 和 Thymeleaf Layout Dialect 的版本
ext['thymeleaf.version'] = '3.0.3.RELEASE'
ext['thymeleaf-layout-dialect.version'] = '2.2.0'
// 自定义 Hibernate 的版本
ext['hibernate.version'] = '5.2.8.Final'
// 使用了 Maven 的中央仓库(你也可以指定其他仓库)
repositories {
//mavenCentral()
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
}
// 依赖关系
dependencies {
// classpath 声明说明了在执行其余的脚本时,ClassLoader 可以使用这些依赖项
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
// 使用插件
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
// 打包的类型为 jar,并指定了生成的打包的文件名称和版本
jar {
baseName = 'jpa-in-action'
version = '1.0.0'
}
// 指定编译 .java 文件的 JDK 版本
sourceCompatibility = 1.8
// 默认使用了 Maven 的中央仓库。这里改用自定义的镜像库
repositories {
//mavenCentral()
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
}
// 依赖关系
dependencies {
// 该依赖对于编译发行是必须的
compile('org.springframework.boot:spring-boot-starter-web')
// 添加 Thymeleaf 的依赖
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
// 添加 Spring Data JPA 的依赖
compile('org.springframework.boot:spring-boot-starter-data-jpa')
// 添加 MySQL连接驱动 的依赖
compile('mysql:mysql-connector-java:5.1.6')
//添加H2的依赖
runtime('com.h2database:h2:1.4.193')
// 该依赖对于编译测试是必须的,默认包含编译产品依赖和编译时依
testCompile('org.springframework.boot:spring-boot-starter-test')
}
application.properties
# THYMELEAF
spring.thymeleaf.encoding=UTF-8
# 热部署静态文件
spring.thymeleaf.cache=false
# 使用HTML5标准
spring.thymeleaf.mode=HTML5
#开启H2 的web控制台
spring.h2.console.enabled=true
三、运行测试
1、持久化到H2
H2是一个开源的关系数据库,性能、小巧,有比较好的兼容性,支持相当标准的sql标准,提供了非常友好的基于web的数据库管理界面
运行项目,浏览器访问并成功添加一组数据 localhost:8080/users
访问H2的web管理界面,浏览器输入localhost:8080/h2-console
2、持久化到mysql
application.properties中添加:(只需要在目标机器上安装配置mysql,并创建名称为blog的数据库,无需建表,运行项目会自动建表)
# DataSource
spring.datasource.url=jdbc:mysql://192.168.8.153/blog?characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
#mysql 6.x
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#mysql 5.x
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# JPA
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto=create-drop
同样的方式启动项目,添加一组数据,成功同步到mysql中