第八章 JPA和缓存
1.JPA
1.1.创建User实体类
public class User {
private Integer uId;
private String uName;
private Integer uGender;
private Integer uAge;
private String uLoginname;
private String uPassword;
private Date uBirth;
private String uEmail;
private String uAddress;
}
1.2.创建UserMapper类
public interface UserMapper {
@Select("select * from department where u_loginname = #{uLoginname} and u_password = #{uPassword}")
public User login(User user);
}
1.3.创建UserController类
@Controller
public class LoginController {
@Autowired
UserMapper userMapper;
@PostMapping(value="/user/login")
public String login(@RequestParam("username")String username,
@RequestParam("password")String password,
Map<String,String> map,
HttpSession session) {
User user = new User();
user.setuLoginname(username);
user.setuPassword(password);
User login = userMapper.login(user);
if(login != null) {
session.setAttribute("loginName", login.getuName());
//session.setAttribute("password", password);
//重定向,防止表单重复提交
return "redirect:/main.html";
}
map.put("message","用户名密码错误!");
return "login";
}
}
1.4.SpringData-JPA简介
SpringData下有三大模块分别是:
Repository support:常应用的是:JPA,因为其中包含大量的CRUD的操作
Templates:SpringData Redis
Object Mapping:SpringData MongoDB
1.5.SpringBoot整合JPA
????????创建项目选择依赖
????????JPA本质上还是一个OPM(实体对象关系映射)【Object Relational Mapping】,首先需要创建项目勾选jpa、web、JDBC和MySQL驱动,既然JPA本质ORP,离不开实体对象,那么我们先创建实体类
????????1.编写User类(实体类),有一个Entity和数据库表去进行映射,并且进行映射关系的配置
//使用JPA注解声明映射关系
@Entity//告诉JPA这是一个实体类(和数据表映射的实体类)
@Table(name="t_user")//告诉JPA与数据库中那张表进行映射
public class User {
@Id//告诉JPA这是主键列
@GeneratedValue(strategy=GenerationType.IDENTITY)//这是使用主键自增的策略
private Integer id;
@Column(name="last_name",length=50)//这是对应的数据表中的一列数据
private String lastName;
@Column(name="email")//省略就是属性名就是数据表中的列名
private String email;
@Column(name="did")
private Integer dId;
????????2.编写Repository接口去继承JAPRepository接口,实现操作数据库的表中的数据
/**
* 继承JpaRepository来实现对数据库进行CRUD的操作
* @author Administrator
*/
public interface UserRepository extends JpaRepository<User, Integer>{
}
????????3.基本配置:yml文件中配置:jpa的创建表和显示执行时的sql语句;
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://101.132.192.20:3306/jpa
username: root
password: 123456
initialization-mode: always
#101.132.192.20
jpa:
hibernate:
#更新或创建实体类对应的数据表
ddl-auto: update
#在执行sql时控制台显示SQL语句
show-sql: true
????????在主程序需要剥离一些SpringBoot自动配置的数据源,否则SpringBoot使用默认数据源!那么自己配置的数据源是不会生效!也就是需要排除自动配置,手动配置(指定)数据源
@EnableAutoConfiguration //把UserRepository初始化,并把其对象放在Spring容器中去
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class})
(exclude = { DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class })
????????4.在pom文件中加上Hibernate的依赖,因为JPA底层是依赖于Hibernate
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
????????在MySQL中创建数据库jpa,接下来运行SpringBootApplication(springboot的启动程序),控制台显示建表sql语句,数据库中t_user表创建成功!
????????5.创建UserController类
@RestController
public class UserController {
@Autowired
UserRepository repository;
@GetMapping("/user")
public User addUser(User user){
User u = repository.save(user);
return u;
}
@GetMapping("/user/{id}")
public User findUserById(@PathVariable("id") Integer id){
Optional<User> opt = repository.findById(id);
return opt.get();
}
}
????????访问地址:http://localhost:8080/user/1
2.缓存
2.1.缓存简介
2.1.1.什么是缓存
????????从三个角度了解缓存:性能:将相应数据存储起来以避免数据的重复创建、处理和传输,可有效提高性能。
????????稳定性:同一个应用中,对同一数据、逻辑功能和用户界面的多次请求时经常发生的。当用户基数很大时,如果每次请求都进行处理,消耗的资源是很大的浪费,也同时造成系统的不稳定。例如,web应用中,对一些静态页面的呈现内容进行缓存能有效的节省资源,提高稳定性。而缓存数据也能降低对数据库的访问次数,降低数据库的负担和提高数据库的服务能力;
????????可用性:有时,提供数据信息的服务可能会意外停止,如果使用了缓存技术,可以在一定时间内仍正常提供对最终用户的支持,提高了系统的可用性。
2.1.2.为什么学习缓存
????????减少交互通讯量:缓存数据能有效减少在进程和机器间的传输量;
????????降低系统中的处理量:减少处理次数;
????????降低需要做的磁盘访问次数:比如缓存在内存中的数据。
2.1.3.缓存数据特点
????????数据量不大;访问频率高;数据更改频率低
2.2.JSR107
????????Java Caching定义了5个核心接口,分别是:CachingProvider, CacheManager, Cache, Entry 和 Expiry。
????????CachingProvider:定义了创建、配置、获取、管理和控制多个CacheManager。一个应用可以在运行期访问多个CachingProvider。
????????CacheManager:定义了创建、配置、获取、管理和控制多个唯一命名的Cache,这些Cache存在于CacheManager的上下文中。一个CacheManager仅被一个CachingProvider所拥有。
????????Cache:是一个类似Map的数据结构并临时存储以Key为索引的值。一个Cache仅被一个CacheManager所拥有。
????????Entry:是一个存储在Cache中的key-value对。
????????Expiry:每一个存储在Cache中的条目有一个定义的有效期。一旦超过这个时间,条目为过期的状态。一旦过期,条目将不可访问、更新和删除。缓存有效期可以通过ExpiryPolicy设置。
2.2.Spring缓存抽象
2.2.1.介绍
????????Spring为了简化缓存开发,定义了org.springframework.cache包下的Cache和CacheManager两个接口来统一不同的缓存技术;并支持使用JCache(JSR-107)注解简化我们开发;Cache接口为缓存的组件规范定义,包含缓存的各种操作集合;Cache接口下Spring提供了各种xxxCache的实现;如RedisCache,EhCacheCache , ConcurrentMapCache等;每次调用需要缓存功能的方法时,Spring会检查检查指定参数的指定的目标方法是否已经被调用过;如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。
????????使用Spring缓存抽象时我们需要关注以下两点:确定方法需要被缓存以及他们的缓存策略;从缓存中读取之前缓存存储的数据
2.2.2.Spring缓存概念以及注解:
概念 | 描述 |
Cache | 缓存接口,定义缓存操作。实现有:RedisCache、EhCacheCache、ConcurrentMapCache等 |
CacheManager | 缓存管理器,管理各种缓存(Cache)组件 |
@Cacheable | 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存 |
@CacheEvict | 清空缓存 |
@CachePut | 保证方法被调用,又希望结果被缓存。 |
@EnableCaching | 开启基于注解的缓存 |
keyGenerator | 缓存数据时key生成策略 |
serialize | 缓存数据时value序列化策略 |
2.3.项目搭建及测试
2.3.1.创建项目测试和使用缓存及环境
????????创建项目需要使用的模块有:core模块下的:cache;web模块下的:web;SQL模块下的:MySQL、MyBatis
????????搭建基本环境:创建数据库:创建出department和employee表;创建实体类:创建实体类封装数据(department和employee类拷贝到项目中);整合MyBatis整合数据库 (配置数据源信息;写mapper接口);创建Service;创建Control。
????????注意:环境搭配正确,如果springboot的版本是2.4.4,mybatis推荐2.1.4
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
2.3.2.建库语句
SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`departmentName` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`lastName` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`gender` int(2) DEFAULT NULL,
`d_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.3.3.拷贝是注意类路径
实体类,加上getter、setter、toString和有参无参构造方法
public class Employee {
private Integer id;
private String lastName;
private String email;
private Integer gender; //性别 1男 0女
private Integer dId;
}
public class Department {
private Integer id;
private String departmentName;
}
2.3.4.整合MyBatis整合数据库(开启驼峰)
????????配置数据源信息
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:// 192.168.202.203:3306/spring_cache
username: root
password: 123456
????????写mapper接口
public interface EmployeeMapper {
@Insert("insert into employee(lastName,email,gender,d_id) values(#{lastName},#{email},#{gender},#{dId})")
public void insertEmp(Employee employee);
@Delete("delect from employee where id = #{id}")
public void deleteEmp(Integer id);
@Update("update employee set lastName=#{lastName},email=#{email},gender=#{gender},dId=#{d_id} where id = #{id}")
public void updateEmp(Employee employee);
@Select("select * from employee")
public List<Employee> selectAllEmp();
@Select("select * from employee where id = #{id}")
public Employee selectEmpNyId(Integer id);
}
????????开启驼峰命名法
mybatis.configuration.map-underscore-to-camel-case=true
2.4.测试类
????????选中项目右键-》Build Path-》Configure Build Path-》Add Library-》JUnit-》选中Junit 4->Apply
@RunWith(SpringRunner.class)
@SpringBootTest
class SpringBootData09Cache1ApplicationTests {
@Autowired
EmployeeMapper employeeMapper;
@Test
void contextLoads() {
Employee emp = employeeMapper.selectEmpNyId(1);
System.out.println(emp.toString());
}
}
2.4.1.创建Service层:EmployeeService类
@Service
public class EmployeeService {
@Autowired
EmployeeMapper mapper;
public Employee findEmpById(Integer id) {
System.out.println("查询id为:" + id +"员工信息!");
return mapper.selectEmpNyId(id);
}
}
2.4.2.创建Controller
@RestController
public class EmployeeControl {
@Autowired
EmployeeService employeeService;
@GetMapping("/emp/{id}")
public Employee getEmpByIt(@PathVariable("id")Integer id) {
return employeeService.findEmpById(id);
}
}
2.4.3.快速体验缓存
????????步骤:1.开启基于注解的缓存(@EnableCaching),启动类
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@MapperScan("com.school.demo.mapper")
@SpringBootApplication
@EnableCaching
public class SpringBootData09Cache1Application {
public static void main(String[] args) {
SpringApplication.run(SpringBootData09Cache1Application.class, args);
}
}
????????2.标注缓存注解(@Cacheable:能够根据方法的请求参数对其结果进行缓存;@CacheEvict: 清空缓存;@CachePut:保证方法被调用,又希望结果被缓存。)
为了控制台方便观看,需要把方法执行时的日志和SQL显示出来:
#开启驼峰命名法校验规则
mybatis.configuration.map-underscore-to-camel-case=true
#输出mapper文件中的日志
logging.level.com.com.zpark.demo.mapper=debug
#输出执行时的SQL语句
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
????????将刚才的方法查询的结果,放到缓存中去,以后调用相同的方法以后,需要到缓存中去找,缓存中没有再去连接数据库查询
????????@Cacheable的几个属性:cacheName/value:指定缓存组件的名字
- CacheManager管理多个Cache组件,对缓存进行CRUD
- key:缓存数据用的key,如果不指定key,默认使用的是方法的参数
- keyGenerator:key的生成器,可以自己指定key的生成器的组件id
- cacheManager:可以指定缓存管理器
- cacheResolver:可以指定缓存解析器
- condition:指定符合条件的情况下才会缓存
- condition="#id > 0":表示参数id>0的时候,才可以缓存到Cache中
- sync:是否使用异步
- unless:unless=“#result == null”
- unless:除非满足条件的情况下不缓存,可以获取到结果进行判断
名字 | 位置 | 描述 |
methodName | root object | 当前被调用的方法名 |
method | root object | 当前被调用的方法 |
target | root object | 当前被调用的目标对象 |
targetClass | root object | 当前被调用的目标对象类 |
args | root object | 当前被调用的方法的参数列表 |
caches | root object | 当前方法调用使用的缓存列表(如@Cacheable(value={"cache1", "cache2"})),则有两个cache |
argument name | evaluation context | 方法参数的名字. 可以直接 #参数名 ,也可以使用 #p0或#a0 的形式,0代表参数的索引; |
result | evaluation context | 方法执行后的返回值(仅当方法执行之后的判断有效,如‘unless’,’cache put’的表达式 ’cache evict’的表达式beforeInvocation=false) |
// 在service进行测试
@Service
public class EmployeeService {
@Autowired
EmployeeMapper mapper;
//@Cacheable(value="Emp",key="#id")
@Cacheable(value="Emp",condition="#id > 1")
public Employee findEmpById(Integer id) {
System.out.println("查询id为:" + id +"员工信息!");
return mapper.selectEmpNyId(id);
}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!