0%

springBoot学习笔记(二)

文档地址:

http://www.spring-boot.org/doc/

数据校验

1、restful风格类型数据校验
1
2
3
4
@RequestMapping("/valid/{group:[a-zA-Z0-9_]+}/{userid}")
public String valid1(@PathVariable("group") String group, @PathVariable("userid") String userid){
return group+":"+userid;
}
2、普通方式参数传递校验
1
2
3
4
5
6
7
8
9
10
@RestController
@Validated //加到方法上无效
public class DemoController {

@RequestMapping("/vatest")
public String validtest2(@NotBlank (message = "请输入姓名!") String name ,
@Email(message = "电子邮件格式错误!") String email){
return name+"------"+email;
}
}
3、对象参数校验

相关注解:

@NotNull 限制必须不为null,注意支持String类型校验 用在integer上报错

@NotEmpty 验证注解的元素值不为 null 且不为空(字符串长度不为0、集合大小不为0) 用在integer上报错

@NotBlank 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格 用在integer上报错

@Pattern(value) 限制必须符合指定的正则表达式

@Size(max,min) 限制字符长度必须在 min 到 max 之间(也可以用在集合上)

@Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

@Max(value) 限制必须为一个不大于指定值的数字

@Min(value) 限制必须为一个不小于指定值的数字

@DecimalMax(value) 限制必须为一个不大于指定值的数字

@DecimalMin(value) 限制必须为一个不小于指定值的数字

@Null 限制只能为null(很少用)

@AssertFalse 限制必须为false (很少用)

@AssertTrue 限制必须为true (很少用)

@Past 限制必须是一个过去的日期

@Future 限制必须是一个将来的日期

@Digits(integer,fraction) 限制必须为一个小数,且整数部分的位数不能超过 integer,小数部分的位数不能超过 fraction (很少用)

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

public class Car {

@Max(value=100,message="id不能大于100")
private int id;

@NotBlank(message="用户名不能为空")
@Length(min = 2, max = 10, message = "用户名 长度必须在 {min} - {max} 之间")
private String name;

@DecimalMin(value="1.0",message="价格最低1元")
@DecimalMax(value="10.0",message="价格最高10元")
private float price;

//格式化日期时间类型
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd hh:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd hh:mm:ss")
private Date createDate;

//忽略字段,不转换为json
@JsonIgnore
private String memo;

//当属性值为空时候,不转换为json
@JsonInclude
@NotNull(message="属性字段不能为空")
@NotBlank(message="属性字段不能为空白")
private String isnull;

@Max(value=1000,message = "id最大1000")
private Integer id;

@Pattern(regexp = "[a-z]+" ,message = "参数a-z")
private String name;

@Max(value = 100,message = "age最大100")
private Integer age;


}

json参数校验

1
2
3
4
5
6

@RequestMapping("/vatest3")
public User validtest3(@RequestBody @Validated User user){
return user;
}

统一异常处理类

使用这个则会直接返回异常信息到页面而不是系统错误信息页面

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
package com.syl.demo01.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.lang.invoke.ConstantCallSite;

/**
* @Auther: Administrator
* @Date: 2019-11-04 20:43
* @Description:统一异常类
*/
@ControllerAdvice
public class CustomExceptioinHandler {


@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
@ResponseStatus
public String test01(ConstraintViolationException e) {
for (ConstraintViolation<?> s : e.getConstraintViolations()) {
return s.getInvalidValue() + ": " + s.getMessage();
}
return "请求参数不合法!";
}
}

springBoot静态资源

默认静态资源映射

Spring Boot 对静态资源映射提供了默认配置

Spring Boot 默认将 /** 所有访问映射到以下目录:

classpath:/static

classpath:/public

classpath:/resources

classpath:/META-INF/resources

如:在resources目录下新建 public、resources、static 三个目录,并分别放入 a.jpg b.jpg c.jpg 图片

浏览器访问

http://localhost:8080/a.jpg

http://localhost:8080/b.jpg

http://localhost:8080/c.jpg

自定义静态资源访问

  • 配置类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.syl.demo01.controller;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
* @Auther: Administrator
* @Date: 2019-11-04 21:58
* @Description:
*/
@Configuration
public class StaticConfiguer implements WebMvcConfigurer {


@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pic/**").addResourceLocations("file:E:\\pic\\");
}
}
// http://localhost:8080/pic/123.jpg访问的是E://pic下的文件
  • 配置application.properties

web.upload-path:这个属于自定义的属性,指定了一个路径,注意要以/结尾;

spring.mvc.static-path-pattern=/**:表示所有的访问都经过静态资源路径;

spring.resources.static-locations:在这里配置静态资源路径,前面说了这里的配置是覆盖默认配置,所以需要将默认的也加上否则static、public等这些路径将不能被当作静态资源路径,在这个最末尾的file:${web.upload-path}之所有要加file:是因为指定的是一个具体的硬盘路径,其他的使用classpath指的是系统环境变量。

1
2
3
4
5
6
web.upload-path=E:/pic/
spring.mvc.static-path-pattern=/**
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,\
classpath:/static/,classpath:/public/,file:${web.upload-path}

#http://localhost:8080/123.jpg访问的是E://pic下的文件

配置文件属性application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#项目端口号
server:
port: 8888

#端口号后面紧跟的伪装项目名
servlet:
context-path: /java001

#定义属性,在java代码里@Value(“${属性名}”获取
name:
jerry
age:
123

#实体类类型 需要在实体类上增加注解 @ConfigurationProperties(prefix="user")
# 在需要这个对象的类或者启动类上加注解 @EnableConfigurationProperties({User.class})
user:
name:"tom"
age:12

自定义配置文件

application.yml是系统默认的配置文件,当然我们也可以创建自定义配置文件,在路径src/main/resources下面创建文件test.properties

注意:spring boot 1.5版本后@PropertySource注解就不能加载自定义的yml配置文件了

springboot整合mybatis

  • 引入依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
  • 在application.yml引入配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#配置数据源
spring:
datasource:
url: jdbc:mysql://localhost:3306/dfdata?serverTimezone=UTC
type: com.alibaba.druid.pool.DruidDataSource
username: root
password: root001
driver-class-name: com.mysql.cj.jdbc.Driver

#springboot整合mybatis
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.syl.demo01.entity

  • 编写service、serviceimpl,在dao包里创建UserMapper.java,在resources文件夹下创建mapper文件夹,在mapper文件夹下创建usermapper.xml,指定nameplace为usermapper.java的全类名路径,最后不要忘了在启动类上加注解包扫描mapper类

UserService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import com.syl.demo01.entity.User;

import java.util.List;

/**
* @Auther: Administrator
* @Date: 2019-11-04 22:38
* @Description:
*/
public interface UserService {
//获取全部用户数据
public List<User> getUserList();
//新增用户数据
public void createUser(User user);
//获取指定id用户信息
public User getUser(Integer id);
//更新指定id用户信息
public void updateUser(Integer id,User user);
//删除指定id用户
public void deleteUser(Integer id);

}

UserServiceImpl.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
package com.syl.demo01.service.impl;

import com.syl.demo01.dao.UserMapper;
import com.syl.demo01.entity.User;
import com.syl.demo01.service.UserTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
* @Auther: Administrator
* @Date: 2019-11-04 22:38
* @Description:
*/
@Service
public class UserServiceImpl implements UserService {

@Autowired
private UserMapper userMapper;

@Override
public List<User> getUserList() {
return userDao.getAll();
}

@Override
public void createUser(User user) {
userDao.save(user);
}

@Override
public User getUser(Integer id) {
return userDao.findOne(id);
}

@Override
public void updateUser(Integer id, User user) {
user.setId(id);
userDao.update(user);
}

@Override
public void deleteUser(Integer id) {
userDao.delete(id);
}

}

UserMapper.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import com.syl.demo01.entity.User;

import java.util.List;

/**
* @Auther: Administrator
* @Date: 2019-11-04 22:39
* @Description:
*/
public interface UserMapper {
List<User> getAll();

void save(User user);

User findOne(Integer id);

void update(User user);

void delete(Integer id);
}

UserMapper.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
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.syl.demo01.dao.UserMapper">

<!-- List<User> getAll();-->
<select id="getAll" resultType="com.syl.demo01.entity.User">
select * from ut
</select>

<!-- void save(User user);-->
<insert id="save" parameterType="com.syl.demo01.entity.User">
insert into ut (id,name,age) values (#{id},#{name},#{age})
</insert>

<!-- User findOne(String id);-->
<select id="findOne" parameterType="java.lang.Integer" resultType="com.syl.demo01.entity.User">
select * from ut where id=#{id}
</select>

<!-- void update(User user);-->
<update id="update" parameterType="com.syl.demo01.entity.User">
update ut set name=#{name},age=#{age} where id=#{id}
</update>

<!-- void delete(Long id);-->
<delete id="delete" parameterType="java.lang.Integer">
delete from ut where id=#{id}
</delete>

</mapper>

Application.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.syl.demo01;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.syl.demo01.dao")
public class Application {

public static void main(String[] args) {
SpringApplication.run(Demo01Application.class, args);
}
}

SpringBoot使用JPA操作数据库

文档地址: https://docs.spring.io/spring-data/jpa/docs/2.2.1.RELEASE/reference/html/#reference

1、添加依赖
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
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
2、在application.yml添加数据库配置
1
2
3
4
5
6
7
8
9
10
11
spring:
datasource:
url : jdbc:mysql://localhost:3306/test2?serverTimezone=GMT%2B8
type : com.alibaba.druid.pool.DruidDataSource
username : root
password : root001
driver-class-name : com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update #create、create-drop 每次运行删除之前的表重新创建数据表 validate 验证数据表结构
show-sql: true
3、编写代码实现简单CRUD

jpa常用注解

注解 作用
@Entity 声明类为实体或表
@Table 声明表名
@Basic 指定非约束明确的各个字段
@Embedded 指定类或它的值是一个可嵌入的类的实例的实体的属性
@Id 指定的类的属性,用于识别(一个表中的主键)
@GeneratedValue 指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值
@Transient 指定的属性,它是不持久的,即:该值永远不会存储在数据库中
@Column 指定持久属性栏属性
@SequenceGenerator 指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列
@TableGenerator 指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表
@AccessType 这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量
@JoinColumn 指定一个实体组织或实体的集合。这是用在多对一和一对多关联
@UniqueConstraint 指定的字段和用于主要或辅助表的唯一约束
@ColumnResult 参考使用select子句的SQL查询中的列名
@ManyToMany 定义了连接表之间的多对多一对多的关系
@ManyToOne 定义了连接表之间的多对一的关系
@OneToMany 定义了连接表之间存在一个一对多的关系
@OneToOne 定义了连接表之间有一个一对一的关系
@NamedQueries 指定命名查询的列表
@NamedQuery 指定使用静态名称的查询
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.springboot.day02.entity;

import javax.persistence.Column;
import javax.persistence.Id;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;

/**
* @Auther: Administrator
* @Date: 2019-11-05 18:14
* @Description:
*/
@Entity
public class User {

@Id
@GeneratedValue
private Integer id;

@Column(name = "name",nullable = true,length = 20)
private String name;

@Column(name = "age",nullable = true, length = 3)
private Integer age;


public User() {}

public User(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}

public Integer getId() { return id;}

public void setId(Integer 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; }
}

接口UserRepository

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.springboot.day02.dao;

import com.springboot.day02.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

/**
* @Auther: Administrator
* @Date: 2019-11-05 18:23
* @Description:
*/

public interface UserRepository extends JpaRepository<User,Integer> {
}

controller层简单增删改查代码

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
package com.springboot.day02.controller;

import com.springboot.day02.dao.UserRepository;
import com.springboot.day02.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

/**
* @Auther: Administrator
* @Date: 2019-11-05 17:16
* @Description:
*/
@RestController
public class JpaTestController {


@Autowired
UserRepository userRepository;

@GetMapping("findAll")
public List<User> findAll(){
return userRepository.findAll();
}

@PostMapping("save")
public String save(User user){
userRepository.save(user);
return "success";
}

@GetMapping("findOne/{id}")
public Optional<User> findone(@PathVariable Integer id){
Optional<User> user = userRepository.findById(id);
System.out.println(user);
return user;
}

@PutMapping("update")
public String update(User user){
User user1 = userRepository.saveAndFlush(user);
if(user1!=null){
return "success";
}
return "fail";
}

@DeleteMapping("delete/{id}")
public String delete(@PathVariable Integer id ){
userRepository.deleteById(id);
return "success";
}
}
4、复杂查询
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
package com.springboot.day02.dao;

import com.springboot.day02.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

/**
* @Auther: Administrator
* @Date: 2019-11-05 18:23
* @Description:
*/

public interface UserRepository extends JpaRepository<User,Integer> {

List<User> findByNameIs(String name);

List<User> findByIdBetween(Integer id1,Integer id2);

List<User> findByIdLessThan(Integer id);

List<User> findByIdLessThanEqual(Integer id);

List<User> findByAgeGreaterThan(Integer id);

List<User> findByAgeAfter(Integer id);

List<User> findByNameIsNotNull();

List<User> findByNameNotNull();

List<User> findByNameIsNull();

List<User> findByNameLike(String name);

List<User> findByIdOrderByAgeDesc(Integer id);

List<User> findByIdOrderByAgeAsc(Integer id);

}
Keyword Sample JPQL snippet
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is,Equals findByFirstnameEquals where x.firstname = ?1
Between findByStartDateBetween where x.startDate between ?1 and ?2
LessThan findByAgeLessThan where x.age < ?1
LessThanEqual findByAgeLessThanEqual where x.age < ?1
GreaterThan findByAgeGreaterThan where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual where x.age >= ?1
After findByStartDateAfter where x.startDate > ?1
Before findByStartDateBefore where x.startDate < ?1
IsNull findByAgeIsNull where x.age is null
IsNotNull,NotNull findByAge(Is)NotNull where x.age not null
Like findByFirstnameLike where x.firstname like ?1
NotLike findByFirstnameNotLike where x.firstname not like ?1
StartingWith findByFirstnameStartingWith where x.firstname like ?1 (parameter bound with appended %)
EndingWith findByFirstnameEndingWith where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining where x.firstname like ?1 (parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc where x.age = ?1 order by x.lastname desc
Not findByLastnameNot where x.lastname <> ?1
In findByAgeIn(Collection ages) where x.age in ?1
NotIn findByAgeNotIn(Collection age) where x.age not in ?1
True findByActiveTrue() where x.active = true
False findByActiveFalse() where x.active = false
IgnoreCase findByFirstnameIgnoreCase where UPPER(x.firstame) = UPPER(?1)
5、自定义查询

dao层接口

1
2
3
4
5
6
7
8
9
10

@Query("select u from User u where name=:name and age=:age")
User findByNameAndAge(String name,Integer age);

@Query("select u from User u where name like %:name%")
List<User> findByNameLike(String name);

//:@Query设置查询的jpsql语句,是面向对象的语法,类似HQL;也可以设置nativeQuery=true来使用原始sql语句。
@Query(value = "select * from user u where length(name)=:length ",nativeQuery = true)
List<User> findNameIsFour(Integer length);

controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//    User findByNameAndAge(String name,Integer age);
@RequestMapping("findByNameAndAge/{name}/{age}")
public User findByNameAndAge(@PathVariable String name,@PathVariable Integer age) {
return userRepository.findByNameAndAge(name,age);
}

// List<User> findByNameLike(String name);
@RequestMapping("findByNameLike/{name}")
public List<User> findByNameLike(@PathVariable String name) {
return userRepository.findByNameLike(name);
}

// List<User> findNameIsFour();
@RequestMapping("findNameIsFour/{len}")
public List<User> findNameIsFour(@PathVariable Integer len) {
return userRepository.findNameIsFour(len);
}
6、SpringBoot 使用JPA @Modifying和@Query、@Transactional注解DML
1
2
3
4
5
6
7
8
9
10

@Modifying
@Transactional
@Query("update User u set name=:name where id=:id")
int updateName(String name,Integer id);

@Modifying
@Transactional
@Query("delete from User where id=:id")
int deleteUser(Integer id);

controller

1
2
3
4
5
6
7
8
9
10
11
12
13
//    int updateName(String name,Integer id);
@RequestMapping("updateName/{name}/{id}")
public String updateName(@PathVariable String name,@PathVariable Integer id) {
int i = userRepository.updateName(name, id);

return i>0?"success":"fail";
}
// int deleteUser(Integer id);
@RequestMapping("deleteUser/{id}")
public String deleteUser(@PathVariable Integer id) {
int i = userRepository.deleteUser(id);
return i>0?"success":"fail";
}
7、jpa分页排序
  • 排序
1
2
3
4
//默认从大到小排序
Sort.sort(Person.class);
//根据某字段排序
Sort.by("firstname").ascending().and(Sort.by("lastname").descending());

dao

1
List<User> findByNameContaining(String name, Sort sort);

controller

1
2
3
4
5
6
@RequestMapping("findByNameContaining/{name}/{filed}")
public List<User> findByNameContaining(@PathVariable String name,@PathVariable String filed) {
List<User> byNameContaining = userRepository.findByNameContaining(name, Sort.by(filed).descending());

return byNameContaining;
}
  • 分页

dao

1
Page<User> findAll(Pageable pageable); //太占内存,不建议使用

controller

1
2
3
4
@RequestMapping("findAllPager")
public Page<User> findAllPager(){
return userRepository.findAll(PageRequest.of(1, 5,Sort.by("age").ascending()));
}

dao

1
Slice<User> findByNameContaining(String name,Pageable pageable);  //内存开销不大,建议使用

controller

1
2
3
4
@RequestMapping("getAll/{name}")
public Slice<User> getAll(@PathVariable String name){
return userRepository.findByNameContaining(name,PageRequest.of(1, 2,Sort.by("age").ascending()));
}
8、一对多
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
@Entity
public class Phone {

@Id
@GeneratedValue
private Integer id;
private String name;
private Integer pid;
}



@Entity
public class Person {

@Id
@GeneratedValue
private Integer id;

@Column(name = "name",length = 20)
private String name;

@OneToMany(mappedBy = "pid",cascade = CascadeType.ALL,fetch = FetchType.EAGER)
private List<Phone> phones;
}

dao

1
2
3
4
5
6
public interface PersonRepository extends JpaRepository<Person, Integer> {

@Query("select p1 from Person p1 ,Phone p2 where p1.id=:id and p1.id=p2.pid")
Person findPerson(Integer id);

}

controller

1
2
3
4
5
6

// Person findPerson(Integer id);
@RequestMapping("findPerson/{id}")
public Person findPerson(@PathVariable Integer id) {
return personRepository.findPerson(id);
}
9、多对多

老师和学生多对多,以老师作为主表维护中间表

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
@Entity
@JsonIgnoreProperties("teachers") //为了防止查询时内存溢出,使用他忽略teachers的json转化
public class Student {
@Id
@GeneratedValue
private Integer id;
private String name;

@ManyToMany(mappedBy = "students") //指定主表中的集合属性名
private List<Teacher> teachers;
}


@Entity
public class Teacher {

@Id
@GeneratedValue
private Integer id;
private String name;


@ManyToMany
@JoinTable(name="tea_stu", //中间表的表名,默认 主表_从表
joinColumns=@JoinColumn(name="tea_id"), //字段一
inverseJoinColumns=@JoinColumn(name="stu_id")) //字段二
private List<Student> students;

10、springBoot中使用Thymeleaf(百里香)

依赖

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

application.yml中配置

1
2
3
4
5
spring:   
#开始thymeleaf设置
thymeleaf:
#禁用模板缓存
cache: false

resources/templates/index.html

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en"
xmlns:th="http://www.thymeleaf.org"> <!-- 引入命名空间 -->
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${message}"></h1>
</body>
</html>

controller

1
2
3
4
5
6
7
8
9
10
11
@Controller
public class ThymeleafController {

@GetMapping("/first")
public String indexPage(Model model) {
String message = "Hello, Thymeleaf!";
model.addAttribute("message", message);
return "index"; //直接返回到 resources/templates/index.html 页面
}

}

从model中取值
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
<!-- 给标签赋值 th:text -->
<h1 th:text="${userName}"></h1>

<!-- 给属性赋值 th:value、th:属性名称 -->
<input type="text" name="names" th:value="${userName}"/>

<!-- 字符串拼接 -->
<span th:text="'欢迎来:'+${userName}+'学习!'"></span>

<!-- 字符串拼接,方式2 -->
<span th:text="|欢迎来:${userName}学习!|"></span>


<!-- 取对象 model.addAttribute("user", u); u.setId(1);-->
<span th:text="${user.id}"></span>


<!-- 取map model.addAttribute("src", map); map.put("src2","0.jpg");-->
<img th:src="${src.src2}"/>

<!-- 取集合遍历 model.addAttribute("userList", list);
其中:
iterStat 称作状态变量,属性有:
index:当前迭代对象的 index(从 0 开始计算)
count:当前迭代对象的 index(从 1 开始计算)
size:被迭代对象的大小
current:当前迭代变量
even/odd:布尔值,当前循环是否是偶数/奇数(从 0 开始计算)
first:布尔值,当前循环是否是第一个
last:布尔值,当前循环是否是最后一个
-->
<tr th:each="u,iterStat : ${userList}">
<td th:text="${u.id}"></td>
<td th:text="${u.name}"></td>
<td th:text="${u.age}"></td>
<td th:text="${iterStat.count}">count</td>
</tr>

<!-- th:if 条件成立就显示 -->
<h1 th:if="${flag=='yes'}" >oh yes</h1>

<!-- th:unless 条件不成立就显示 -->
<h1 th:unless="${flag=='no'}" >oh No</h1>

<!-- switch选择语句
model.addAttribute("flag", "yes");
model.addAttribute("menu", "admin");
model.addAttribute("manager", "manager");
-->
<div th:switch="${menu}">
<p th:case="'admin'">User is an administrator</p>
<p th:case="${manager}">User is a manager</p>
</div>
  • 静态资源加载

    在Springboot中,默认读取thymeleaf文件的路径是:src/main/resource/templates

1
<link rel="stylesheet" type="text/css" media="all"  href="../../css/gtvg.css"  th:href="@{/css/gtvg.css}" />

​ 当我们在没有后台渲染的情况下,浏览器会认得href, 当我们在有后台渲染的情况下,后台会把这个标签渲染为这样:

1
<link rel="stylesheet" type="text/css" media="all" href="/css/gtvg.css"  />
  • Thymeleaf 片段fragment定义使用

    resource/templates 下,新增模板文件footer.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<body>
  <h1 th:fragment="copy">
&copy; 1999-2018 Offcn.All Rights Reserved
</h1>
</body>

</body>
</html>

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!--
th:insert:保留自己的主标签,保留th:fragment的主标签。
th:replace:不要自己的主标签,保留th:fragment的主标签。
th:include:保留自己的主标签,不要th:fragment的主标签。(官方3.0后不推荐)
-->
<!-- 把片段的内容插入到当前位置 -->
<div th:insert="~{footer :: copy}"></div>

</br>
<!-- 使用片段的内容替换当前标签 -->
<div th:replace="~{footer :: copy}"></div>
</br>
<!-- 保留自己的主标签,不要片段的主标签 -->
<div th:include="~{footer :: copy}"></div>

  • 常见内置工具对象

    #dates

    #numbers

    #strings

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
时间:<span th:text="${#dates.format(date,'yyyy-MM-dd HH:mm:ss')}">4564546</span></br>    

<!-- public String formatDecimal(Number target, 目标数字
Integer minIntegerDigits, 最小整数位,不够就在前面加0
Integer decimalDigits 小数点后保留位数
) -->
金额:<span th:text="'¥'+${#numbers.formatDecimal(price, 1, 2)}">180</span> </br>

<!-- # 这里的含义是 如果 atc.text 这个变量多余200个字符,后面显示... 这里显示57个有效字符,再加三个.-->
<p th:text="${#strings.abbreviate(strText,60)}">内容内容内容</p>

<!-- 判断字符串是否为空 -->
<span th:if="${!#strings.isEmpty(str2)}">字符串str2不为空</span></br>

<!-- 截取字符串,指定长度 -->
<span th:text="${#strings.substring(str2,0,4)}">字符串str2的值</span>
</body>

  • 其他
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- 引入bootstrap的jar包 -->
<input type="text" class="form-control" name="name" id="name" th:value="*{name}" placeholder="name"/>

<!-- a链接 -->
<a href="toAdd" th:href="@{toAdd}" class="btn btn-info">add</a>


<!-- 循环 -->
<tr th:each="user : ${page}">
<th scope="row" th:text="${user.id}">1</th>
<td th:text="${user.name}">neo</td>
<td th:text="${user.age}">6</td>
<td><a th:href="@{'toEdit/'+${user.id}}">edit</a></td>
<td><a th:href="@{'delete/'+${user.id}}">delete</a></td>
</tr>

<!-- 表单提交 -->
<form class="form-horizontal" th:action="@{add}" method="post"></form>

<!-- 数据回显 -->
<form class="form-horizontal" th:action="@{/manageruser/edit}" th:object="${user}" method="post">
<input type="text" name="name" th:value="*{name}" />
</form>
赏口饭吃吧!