JPA的使用
1、JPA的简介
Spring data JPA是Spring在ORM框架,以及JPA规范的基础上,封装的一套JPA应用框架,并提供了一整套的数据访问层解决方案,统一接口Respository,Spring Data JPA 让我们摆脱了DAO层的操作,基本的CRUD都可以依赖于它来实现。可以极大的提高开发的效率
1、@Query以及方法映射的使用方式
- 导入坐标
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
- properties文件书写
#springboot-jpa
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
#指定所使用的数据源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#每次运行程序,没有表格会新建表格,表内有数据不会清空,只会更新
spring.jpa.hibernate.ddl-auto=update
#显示sql语句
spring.jpa.show-sql=true
-
实体类编写
@Data @AllArgsConstructor @NoArgsConstructor //tell to jap this is a entity @Entity //this is the name of the table @Table(name = "student") public class StudentModel { @Id //this is a primary key private Long id; @Column //this is a represent of database's column,default: omit private String name; private Integer age; private String email; } -
Controller层编写
@RestController
@RequestMapping("/test")
public class StudentController {
@Autowired
StudentService studentService;
@RequestMapping("/jpa")
public List<StudentModel> getList() {
List<StudentModel> list = studentService.getUserList();
return list;
}
@RequestMapping("/save")
public String saveStudent(@RequestBody StudentModel studentModel) {
studentService.saveStudent(studentModel);
return "Ok";
}
@RequestMapping("/get/{id}")
public StudentModel getOne(@PathVariable("id") int id) {
StudentModel studentModel = studentService.getOne(id);
return studentModel;
}
@RequestMapping("/get/sql")
public String QuerySql() {
studentService.QuerySql();
return "studentModel";
}
}
- Dao层编写
/ extend JpaRepository's interface , pass by value entity, primary key's type
//JpaRepository=》PagingAndSortingRepository=》CrudRepository=》Repository
/*
Hibernate实现了jpa操作
*/
public interface StudentDao extends JpaRepository<StudentModel,Integer>, JpaSpecificationExecutor<StudentModel> {
//?1 jpa的语法,表示要加的参数的下标,就行取值对应,index 1 代表的是第一个参数
@Query(value = "from StudentModel where name = ?1 ")//从实体类中进行查询,然后会自动的进行拼接,
List<StudentModel> findJpql(String name);
//:id 表示的是将jpql语句中的占位符和方法中的参数进行一一的对应
@Query(value = "from StudentModel where name = :name and id = :id")//参数的位置要和jpql中的占位符的位置保持一一致
StudentModel findQuery(String name,int id);
/*
@Query只是代表的是进行查询, 需要使用 @Modifying声明此方法使用来更新操作的
修改或者删除,需要添加上事务
*/
@Query(value = "update StudentModel set name =:name where id = :id")
@Modifying
@Transactional
void updateStudent(int id, String name);
/**
* 使用的是sql语句进行查询,nativeQuery相当于将sql写到数据库进行查询
* @return
*/
@Query(value = "select * from student",nativeQuery = true)
List<StudentModel> findALLJpa();
StudentModel findByName(String name);
/*
报错 JDBC style parameters (?) are not supported for JPA queries
高版本的springBoot不支持?需要加上index,从1开始的,或者
*/
- service层编写
@Override
public void QuerySql() {
/*
sql查询,jpql
1.需要将JPQL语句配置到接口方法上面
2.忒有的查询需要再dao接口上面配置方法
3.在新增的方法上面,使用注解的方式配置jpql查询语言 注解 @QUERY
*/
String name = "xxxxxxxxxxxxxxxxxxx";
// 报错: query did not return a unique result: 5 说明查询出来的结果大于1条
List<StudentModel> list = studentDao.findJpql(name);
System.out.println(list);
System.out.println("================");
//复杂的查询条件
int id = 1;
StudentModel studentModel = studentDao.findQuery(name,id);
System.out.println(studentModel);
System.out.println("============");
// 更新操作
studentDao.updateStudent(id,name);
System.out.println("aaaaaaaaaa");
// 查询全部 sql
List<StudentModel> allJpa = studentDao.findALLJpa();
System.out.println(allJpa);
// 条件查询的方法,不用书写注解
StudentModel student = studentDao.findByName(name);
System.out.println("bbbbbbbbbbbbbbbb");
System.out.println(student);
2、JpaSpecificationExecutor<实体类名字>多条件拼接查询
@Service
public class TeacherServiceImpl implements TeacherService {
@Autowired
TeacherDao teacherDao;
@Autowired
StudentDao studentDao;
@Override
public TeacherModel getTeacherAndStudent(int id) {
TeacherModel teacher = this.teacherDao.getById(id);
Specification<StudentModel> studentModelSpecification = new Specification<StudentModel>() {
//
@Override
public Predicate toPredicate(Root<StudentModel> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
/*
root: 代表我们查询的根对象,需要查询的任何属性都可以从根对象中进行获取
CriteriaQuery: 顶层查询对象,自定义查询方式
CriteriaBuilder: 查询的构造器,封装了很多的查询条件
*/
// 获取到要比较的属性
Path<Object> tid = root.get("tid");
// 构建查询的方式
Predicate equal = criteriaBuilder.equal(tid, id);
return equal;
}
};
List<StudentModel> list = studentDao.findAll(studentModelSpecification);
TeacherModelDto teacherModelDto = new TeacherModelDto();
BeanUtils.copyProperties(teacher,teacherModelDto);
teacherModelDto.setList(list);
return teacherModelDto;
}
}
RestTemplate服务之间的调用
1、介绍:
RestTemplate是spring框架中自带的rest客户端工具类,具有丰富的API,并且在spring cloud中,标记@LoadBalanced注解,可以实现客户端负载均衡的rest调用.
由于RestTemplate为spring框架中自带的工具类。故不用专门在pom中引入依赖。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4ZwuSMBX-1675843489314)(C:\Users\guanbin.yang\AppData\Roaming\Typora\typora-user-images\image-20211212105715882.png)]
2、调用服务模块ygb:
- config编写:
@Configuration//声明为配置类注解
public class RestTemplateConfig {
@Bean//交给spring容器进管理
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
- controller层编写
@RestController
@RequestMapping("/rest")
public class RestTemplateController {
@Autowired
RestTemplateService restTemplateService;
/**
* 通过id进行查找teacher
* @param id
* @return
*/
@RequestMapping("/{id}")
public ResponseEntity<TeacherModelDto> getlist(@PathVariable("id") int id) {
ResponseEntity<TeacherModelDto> teacher = restTemplateService.getStudentList(id);
return teacher;
}
/**
*
* @param studentModel
* @return
*/
@RequestMapping("/save")
public String getStudentList(@RequestBody StudentModel studentModel) {
restTemplateService.save(studentModel);
return "list";
}
}
- service层编写
package com.hema.middleware.service.impl;
import com.alibaba.fastjson.JSON;
import com.hema.middleware.data.dto.TeacherModelDto;
import com.hema.middleware.model.StudentModel;
import com.hema.middleware.model.TeacherModel;
import com.hema.middleware.service.RestTemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@Service
public class RestTemplateServiceImpl implements RestTemplateService {
@Autowired
RestTemplate restTemplate;
@Value("${url}")
private String url;
@Override
public ResponseEntity<TeacherModelDto> getStudentList(int id) {
//要调用接口的url,以及接口返回对象的类型
//getForObject --- optionsForAllow 分为一组,这类方法是常规的 Rest API(GET、POST、DELETE 等)方法调用;
//exchange:接收一个 RequestEntity 参数,可以自己设置 HTTP method,URL,headers 和 body,返回 ResponseEntity;
//execute:通过 callback 接口,可以对请求和返回做更加全面的自定义控制。
return restTemplate.getForEntity(url+id,TeacherModelDto.class);
}
@Override
public void save(StudentModel studentModel) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
//将调用yxh下的入口的参数封装成StudentModel的Json字符串的形式
HttpEntity<String> entity = new HttpEntity<>(JSON.toJSONString(studentModel),headers);
//参数声明,url要调用服务的地址,请求的类型,接口封装的HttpEntity实体类对象,以及接口返回值的类型
restTemplate.exchange(url,HttpMethod.POST,entity,String.class).getBody();
}
// @Override
// public List<StudentModel> getList(int id) {
//
// restTemplate.exchange(url+id,HttpMethod.POST,StudentModel,StudentModel.class).getBody();
// return ;
// }
}
@Service
public class RestTemplateServiceImpl implements RestTemplateService {
@Autowired
RestTemplate restTemplate;
@Value("${url}")
private String url;
@Override
public ResponseEntity<TeacherModelDto> getStudentList(int id) {
//要调用接口的url,以及接口返回对象的类型
return restTemplate.getForEntity(url+id,TeacherModelDto.class);
}
@Override
public void save(StudentModel studentModel) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
//将调用yxh下的入口的参数封装成StudentModel的Json字符串的形式
HttpEntity<String> entity = new HttpEntity<>(JSON.toJSONString(studentModel),headers);
//参数声明,url要调用服务的地址,请求的类型,接口封装的HttpEntity实体类对象,以及接口返回值的类型
restTemplate.exchange(url,HttpMethod.POST,entity,String.class).getBody();
}
// @Override
// public List<StudentModel> getList(int id) {
//
// restTemplate.exchange(url+id,HttpMethod.POST,StudentModel,StudentModel.class).getBody();
// return ;
// }
}
Spring中Cacheable使用
1、介绍
- Spring Cache是作用在方法上的,其核心思想是这样的:当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值对存放在缓存中,等到下次利用同样的参数来调用该方法时将不再执行该方法,而是直接从缓存中获取结果进行返回。所以在使用Spring Cache的时候我们要保证我们缓存的方法对于相同的方法参数要有相同的返回结果。
- 我们要做的事情
1.声明那些方法需要做缓存处理
2.配置spring对缓存的支持,一种是使用注解,一种是使用xml配置文件
2、Cacheable中的常用的注解
@Cacheable(value="users", key="#id",caondition="#user.id==0"):可以标注在方法上面,或者类上面,标注在方法上表示该方法支持缓存,如过标记在类上,表示该类下的所有方法都支持缓存, value属性是必须指定的,其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称。如果不指定key的话,系统会默认的生成,我们,还可以自定义key,以及指定缓存发生的条件
@CachePut: 在支持Spring Cache的环境下,对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
@CacheEvict:@CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的语义与@Cacheable对应的属性类似。即value表示清除操作是发生在哪些Cache上的(对应Cache的名称);key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key;condition表示清除操作发生的条件。allEntries属性:表示是否需要清除缓存中的所有元素。默认为false,表示不需要。当指定了allEntries为true时,Spring Cache将忽略指定的key。beforeInvocation:清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。
@Caching:@Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。
@CacheConfig:有时候一个类中可能会有多个缓存操作,而这些缓存操作可能是重复的。这个时候可以使用@CacheConfig
下面介绍一下 @Cacheable 这个注解常用的几个属性:
cacheNames/value:用来指定缓存组件的名字key:缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。(这个 key 你可以使用 spEL 表达式来编写)keyGenerator:key 的生成器。 key 和 keyGenerator 二选一使用cacheManager:可以用来指定缓存管理器。从哪个缓存管理器里面获取缓存。condition:可以用来指定符合条件的情况下才缓存unless:否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然你也可以获取到结果进行判断。(通过#result获取方法结果)sync:是否使用异步模式。
3.对于支持缓存的方法
Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。Spring在缓存方法的返回值时是以键值对进行缓存的,值就是方法的返回结果,至于键的话,除了使用方法参数作为key之外,Spring还为我们提供了一个root对象可以用来生成key。通过该root对象我们可以获取到以下信息:
| 属性名称 | 描述 | 示例 |
|---|---|---|
| methodName | 用当前的方法名当作key | #root.methodName |
| method | 用当前方法当做key | #root.method.name |
| target | 当前被调用的对象 | #root.target |
| targetClass | 被调用对象的class | #root.targetClass |
| args | 当前方法参数组成的数组为key | #root.args[0] |
| caches | 当前被嗲用的方法使用的Cache | #root.caches[0].name |
2、添加redis依赖
<!-- 添加该依赖后,将自动使用 Redis 作为 Cache Provider -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
3、添加reid的配置文件:
#连接redis的配置信息
spring.redis.host=127.0.0.1
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码(默认为空)
spring.redis.password=
#连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
#连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
#连接池中的最大空闲连接
spring.redis.pool.max-idle=8
#连接池中的最小空闲连接
spring.redis.pool.min-idle=0
#连接超时时间(毫秒)
spring.redis.timeout=30000
# Redis数据库索引(默认为0)
spring.redis.database=0
4、添加实现Serializable接口的实体类
package com.hema.middeware.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
//tell to jap this is a entity
@Entity
//this is the name of the table,还可以指定索引
@Table(name = "student")
public class StudentModel implements Serializable {
@Id //this is a primary key
@GeneratedValue(strategy = GenerationType.AUTO)//主键自增
private Integer id;
@Column//this is a represent of database's column,default: omit
private String name;
private Integer age;
private String email;
private Integer tid;
}
1934

被折叠的 条评论
为什么被折叠?



