梦入琼楼寒有月,行过石树冻无烟

Spring boot and Thymeleaf Data visit this Spring Data and Hibernate

本章节主要用于讲述和演示Spring boot配合Thymeleaf做数据访问的相关案例和技术演示,即通过本章章节“Spring boot and Thymeleaf Data visit”即“spring boot 和 Thymeleaf数据访问”。

本章将通过Spring Data JPA、Spring boot MyBatis、Spring boot REST、Spring boot MongoDB、Spring boot Redis、以及数据缓存Cache来进行讲解。Spring Data 是Spring 访问数据库的一大堆解决方案,包含大量的关系型数据库以及非关系型数据库的数据访问解决方案。

Spring Data JPA

Spring Data JPA从名称中我们可以得到,Spring Data JPA是Spring Data的子项目,在学习Spring Data Jpa之前,我们先学习下Hibernate,与其说是Spring Data JPA,更不如说是Hibernate,因为Spring Data JPA的功能,基本上都是由Hibernate所实现的。

从Spring Data JPA中我们可得知,Spring Data JPA的全程是Java Persistence API,即Java持久性映射,而Java持久性映射则是由官方提出的Java持久化规范,通过注解或XML描述对象的一种映射关系,将内存中的实体对象来操纵数据库,Spring Data JPA通过提供基于JPA的仓库极大的简化了JAP的写法,在不写实现类的时候,即可实现数据库的访问操作。

Spring Data 体系结构

ID DA FA FD
1 Persistence 用于获取EntityManagerFactory实例的静态方法类 EntityManagerFactory
2 EntityManagerFactory 是一个EntityManager的工厂类,创建并管理许多EntityManager的实例 EntityManager
3 EntityManager 是一个接口,用于查询实例并控制对象的持久化操作
4 Entity Entity是作为记录存储在数据库中的持久性对象
5 Persistence Unit Persistence Unit 定义了一组所有的实体类,在应用程序中由 EntityManager实例来管理(实体类集表示存储中的数据) EntityManager
6 EntityTransaction EntityTransaction class与EntityManager class有对应的关系,对于每个EntityManage,都是由EntityTransaction类进行维护 EntityTransaction
7 Query 由每一个JPA大熔炉实现的借口,用于获取满足条件的关系对相爱

Spring Data 对象映射关系

在对象映射关系(Object Relational Mapping)中,Java Object到数据库表的映射过程被称之为对象关系映射,对象关系映射被充当关系数据库和Java class\object之间的桥梁

Hibernate

Hibernate是一个开源的对象关系映射框架,对JDBC进行了非常轻量级的对象封装,从文档中我们可以得知,他将普通Java对象,与数据库建立映射关系,是一个全自动的对象关系映射框架,Hibernate由于通过普通Java对象与数据库建立映射关系,所以从而可达到自动生成SQL语句并执行的功能,让开发人员摆脱烦恼,一盏到底。

Hibernate and Spring Data JPA 区别

Jap可以理解为是一个标准接口,而Hibernate则是一个实现,但是功能什么的都是JPA所提供的,Hibernate主要通过三个组件来实现,分别时hibernate-annotation、hibernate-entitymanager、Hibernate三个组件来实现:

hibernate-annotation

hibernate-annotation是Hibernate支持annotatio方法配置的基础,主要包括了标准的Jpa annotation以及Hibernate自身功能的annotation。

hibernate-core

hibernate-core是Hibernate的核心,主要功能则是实现,因为最主要的,还是需要看到的。

hibermate-entitymanager

hibermate-entitymanager实现了标准的JPA,是一个hibernate-core和JPA的适配器,并不直接提供对象映射关系(Object Relational Mapping),而是对hibernate-core进行封装,让他符合JPA的代码规范。

Spring data jpa + hibernate

在项目创建完成后,通过访问http://localhost:8080/demo/save/来进行插入数据,之后当显示插入成功后访问http://localhst:8080/demo/findAll来查看所有用户信息,当然我们还可以通过访问http://localhost:8080/demo/findByUsernameLike?username=k,来进行模糊搜索,除此之外,我们还可以通过访问http://localhost:8080/demo/getOne?id=1来通过id进行查找信息。

构建项目

Spring data jpa and thymeleaf

在开始对项目编写之前,需要使用Spring Initializrl来创建spring boot项目,并添加Tthymeleaf、Spring Data JPA、Spring boot Web的支持,然后对项目pom.xml进行一定的配置。

pom.xml

pom.xml在本次的过程中主要用于添加MySQL依赖,其MySQL版本为5.6.50,但由于版本过高并没有直接使用此版本的依赖而是使用5.1.45的数据库依赖,以下是pom.xml信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

在这个过程中,如果xml配置文件出现问题,而这里的问题指的是xml文件下在mysql部分中存在红色的波浪线,可通过重新下载maven依赖包来解决:

mvn -U idea:idea

application.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# [servlet]
server.servlet.context-path=/demo
# [thymeleaf] 关闭html缓存
spring.thymeleaf.cache=false
# [datasource] 指定数据库
spring.datasource.url=jdbc:mysql://localhost:3306/test?
# 数据库帐号与密码 username&password
spring.datasource.username=root
spring.datasource.password=toor
# 加载数据库驱动 com.mysql.jdbc.Driver
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# [jpa] 指定数据库类型为MySQL
spring.jpa.database=mysql
# 是否在日志中显示SQL语句
spring.jpa.show-sql=true
# 是否自动创建、更新数据库表等配置信息,如果存在则不需要创建,不存在时才创建
spring.jpa.hibernate.ddl-auto=update

在spring boot的全局配置文件application.properties中,配置关闭thymleaf缓存来达到不用重启就能看到修改后结果的需求,并指定其目录、数据库、数据库类型等功能,详情可通过阅读配置文件即可。

实体

MyUser.java

在com.demo下创建example,然后在创建entity包,之后创建MyUser实体类,定义表名称为“user_name”和主键username、age、gender、id等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.demo.example.entity;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "user_name")
public class MyUser implements Serializable {
private static final long serialVersionUID = 1L;
/*
|-user_name 表中的主键分别为
|----|- id int
|----|- age int
|----|- username string
|----|- gender string
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private int age;
private String username;
private String gender;

// id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}

// age
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}

// username
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}

// gender
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}

数据访问层

UserRepository.java

1
2
3
4
5
6
7
8
9
10
11
12
package com.demo.example.repository;

import java.util.List;
import com.demo.example.entity.MyUser;
import org.springframework.data.jpa.repository.JpaRepository;


public interface UserRepository extends JpaRepository<MyUser, Integer> {
public MyUser findByUsername(String username);
public List<MyUser>findByUsernameLike(String username);
}

创建业务层

UserService.java

1
2
3
4
5
6
7
8
9
10
11
12
package com.demo.example.service;

import java.util.List;
import com.demo.example.entity.MyUser;

public interface UserService {
public void saveAll();
public List<MyUser>findAll();
public MyUser findByUsername(String username);
public List<MyUser>findByUsernameLike(String username);
public MyUser getOne(int id);
}

UserServicelmpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.demo.example.service;

import java.util.ArrayList;
import java.util.List;
import com.demo.example.entity.MyUser;
import com.demo.example.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;

@Override
public void saveAll() {
MyUser myUser1 = new MyUser();
myUser1.setUsername("kunlunsiqu");
myUser1.setGender("N");
myUser1.setAge(20);
MyUser myUser2 = new MyUser();
myUser2.setUsername("flydata");
myUser2.setGender("M");
myUser2.setAge(21);
MyUser myUser3 = new MyUser();
myUser3.setUsername("gscssd");
myUser3.setGender("N");
myUser3.setAge(30);
List<MyUser> users = new ArrayList<MyUser>();
users.add(myUser1);
users.add(myUser2);
users.add(myUser3);
userRepository.saveAll(users);
}

@Override
public List<MyUser> findAll() {
return userRepository.findAll();
}
@Override
public MyUser findByUsername(String username) {
return userRepository.findByUsername(username);
}
@Override
public List<MyUser> findByUsernameLike(String username) {
return userRepository.findByUsernameLike("%" + username + "%");
}

@Override
public MyUser getOne(int id) {
return userRepository.getOne(id);
}
}

控制器类

UserController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.demo.example.service.UserService;


@Controller
public class UserController {
@Autowired
private UserService userService;

@RequestMapping("/save")
@ResponseBody
public String save() {
userService.saveAll();
System.out.println("UserController");
return "保存成功";
}
@RequestMapping("/findByUsername")
public String findByUsername(String username, Model model) {
model.addAttribute("title","根据名称查询");
model.addAttribute("auser", userService.findByUsername(username));
return "showAuser";
}
@RequestMapping("/getOne")
public String getOne(int id, Model model) {
model.addAttribute("title","根据名称id查询");
model.addAttribute("auser", userService.getOne(id));
return "showAuser";
}
@RequestMapping("findAll")
public String findAll(Model model) {
model.addAttribute("title", "查询所有");
model.addAttribute("allUsers", userService.findAll());
return "showAll";
}
@RequestMapping("/findByUsernameLike")
public String findByUsernameLike(String username,Model model) {
model.addAttribute("title","用户名模糊查询");
model.addAttribute("allUsers", userService.findByUsernameLike(username));
return "showAll";
}
}

Thymeleaf

showAll.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>showAll</title>
</head>
<body>
<h5>Java Spring Data JPA and MySQL + Thymeleaf</h5>
<p th:text="${title}"></p>
<hr/>
<table>
<tr>
<th>序号</th>
<th>名称</th>
<th>性别</th>
<th>年龄</th>
</tr>
<tr th:each="user: ${allUsers}">
<td>
<p th:text="${user.getId()}"></p>
</td>
<td>
<p th:text="${user.getUsername()}"></p>
</td>
<td>
<p th:text="${user.getGender()}"></p>
</td>
<td>
<p th:text="${user.getAge()}"></p>
</td>
</tr>
</table>
</body>
</html>

showAuser.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>showAuser</title>
</head>
<body>
<h5>Java Spring Data JPA and MySQL + Thymeleaf</h5>
<p th:text="${title}"></p>
<hr/>
<table>
<tr>
<th>序号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
</tr>
<tr>
<td>
<p th:text="${auser.id}"></p>
</td>
<td>
<p th:text="${auser.username}"></p>
</td>
<td>
<p th:text="${auser.gender}"></p>
</td>
<td>
<p th:text="${auser.age}"></p>
</td>
</tr>
</table>
</body>
</html>
⬅️ Go back