SpringBoot2.0.4使用JPA和Redis

      近来研究SpringBoot持久化与缓存的问题,搜集资料做了一个Demo。

      环境:Win10、JDK1.8、IDEA、Redis、Mysql5.7、Redis3.2、SpringBoot2.0.4Release版

第一步建立一个学生表:

CREATE TABLE `student` (
  `sid` int(11) DEFAULT NULL,
  `sname` varchar(32) DEFAULT NULL,
  `sage` int(11) DEFAULT NULL,
  `ssex` varchar(8) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `student` VALUES ('1', '刘一', '18', '男');
INSERT INTO `student` VALUES ('2', '钱二', '19', '女');
INSERT INTO `student` VALUES ('3', '张三', '17', '男');
INSERT INTO `student` VALUES ('4', '李四', '18', '女');
INSERT INTO `student` VALUES ('5', '王五', '17', '男');
INSERT INTO `student` VALUES ('6', '赵六', '19', '女');

第二步用IDEA搭建一个SpringBoot的web项目,SQL项勾选JPA、Mysql、JDBC,NoSQL项勾选Redis,把需要的类都写上

SpringBoot2.0.4使用JPA和Redis_第1张图片

SpringBoot2.0.4使用JPA和Redis_第2张图片

SpringBoot2.0.4使用JPA和Redis_第3张图片

项目搭好整体结构如图:

SpringBoot2.0.4使用JPA和Redis_第4张图片

application.yml配置如下,选用阿里的Druid连接池

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/testmb4
    type: com.alibaba.druid.pool.DruidDataSource
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379

pom.xml文件如下:



	4.0.0

	com.bonc
	boot-hibernate
	0.0.1-SNAPSHOT
	jar

	boot-hibernate
	Demo project for Spring Boot

	
		org.springframework.boot
		spring-boot-starter-parent
		2.0.4.RELEASE
		 
	

	
		UTF-8
		UTF-8
		1.8
	

	
		
			org.springframework.boot
			spring-boot-starter-data-jpa
		
		
			org.springframework.boot
			spring-boot-starter-jdbc
		
		
			org.springframework.boot
			spring-boot-starter-web
		
		
			org.springframework.boot
			spring-boot-starter-data-redis
		

		
			mysql
			mysql-connector-java
			runtime
		
		
			org.springframework.boot
			spring-boot-starter-test
			test
		

		
			com.alibaba
			druid-spring-boot-starter
			1.1.10
		

		
		
			org.projectlombok
			lombok
			1.18.0
			provided
		
	

	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	



StudentController代码如下:

package com.bonc.boothibernate.web;

import com.bonc.boothibernate.common.GeneralResponse;
import com.bonc.boothibernate.entity.Student;
import com.bonc.boothibernate.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/stu")
public class StudentController {

    @Autowired
    private StudentService studentService;
    //单查
    @PostMapping("/getInfo")
    public GeneralResponse getStudent(@RequestParam Integer sid) {

        GeneralResponse generalResponse = new GeneralResponse();
        generalResponse.setData(studentService.getOne(sid));

        return generalResponse;
    }
    //全查
    @PostMapping("/getAll")
    public GeneralResponse getStudents() {
        GeneralResponse generalResponse = new GeneralResponse();
        generalResponse.setData(studentService.findAll());
        return generalResponse;
    }
    //分页功能
    @PostMapping("/findBySepc")
    public GeneralResponse findBySepc(@RequestParam int page, @RequestParam int size) {
        GeneralResponse generalResponse = new GeneralResponse();
        generalResponse.setData(studentService.findBySepc(page,size));
        return generalResponse;
    }

    @PostMapping("/findBySepcLessThan")
    public GeneralResponse findBySepcLessThan(@RequestParam int sid) {
        GeneralResponse generalResponse = new GeneralResponse();
        generalResponse.setData(studentService.findBySidLessThan(sid));
        return generalResponse;
    }

}

StudentServiceImpl代码如下:

package com.bonc.boothibernate.service.impl;

import com.bonc.boothibernate.entity.Student;
import com.bonc.boothibernate.repository.StudentRepository;
import com.bonc.boothibernate.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.*;
import java.util.List;

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StudentRepository studentRepository;

    @Override
    public Student getOne(Integer sid) {
        Student student = (Student)redisTemplate.opsForValue().get(sid);
        if(student==null){
            System.out.println("redis没存好了"+sid);
            Student student1 = studentRepository.getOne(sid);
            redisTemplate.opsForValue().set(sid,student1);
            return student1;
        }
        System.out.println("redis存好了"+sid);
        return student;
    }

    @Override
    public List findAll() {
        return studentRepository.findAll();
    }

    @Override
    public Page findBySepc(int page, int size) {
        PageRequest pageRequest = PageRequest.of(page,size);
        Page students = studentRepository.findAll(new Specification(){
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                Path snamePath = root.get("sname");
            
                //这里可以设置任意条查询条件
                query.where(cb.like(snamePath, "张%"));

                //这种方式使用JPA的API设置了查询条件,所以不需要再返回查询条件Predicate给Spring Data Jpa,故最后return null;即可。
                return null;
            }

        },pageRequest);
        return students;
    }

}


StudentService接口代码可以推断,这里就不贴了。

StudentRepository代码如下:(这里啰嗦一句,传统喜欢叫-Dao,MyBatis用-Mapper,SpringBoot-data-jpa则用-Repository)

package com.bonc.boothibernate.repository;

import com.bonc.boothibernate.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface StudentRepository extends JpaRepository,JpaSpecificationExecutor {

}

如果你没有用过SpringBoot JPA,那么你可能会怀疑这个Repository没有东西是不是错了,事实上,简单查询就是这么简单。

复杂应用参见:https://blog.csdn.net/zab635590867/article/details/81775086

Student代码如下:

package com.bonc.boothibernate.entity;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;

import javax.persistence.*;
import java.io.Serializable;

@Entity
@Data
@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})
public class Student implements Serializable{

    private static final long serialVersionUID = -509438491019594820L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer sid;

    @Column(length = 20)
    private String sname;

    @Column(length = 20)
    private Integer sage;

    @Column(length = 10)
    private String ssex;

}

@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"}) 本来常规是不需要的,报了异常,网上搜到的用法,挺管用的。大神如有更好的解决方法,欢迎留言。

RedisConfig的代码:

package com.bonc.boothibernate.config;

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;

@Configuration
@EnableCaching
public class RedisConfig {
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setKeySerializer(new GenericJackson2JsonRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setHashKeySerializer(new GenericJackson2JsonRedisSerializer());
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        return template;
    }
}

这里的配置主要解决redis缓存对象用。不配置,对象存到redis中就会报各种类型转换异常。

GeneralResponse是一个普通的响应类,前后端分离的项目,大多数的响应类都长这个样子,用了一个常用的插件lombok,主要省点getter和setter,如果报错请在IDEA中下载lombok插件后使用:

package com.bonc.boothibernate.common;

import lombok.Data;

/**
 * @author Jackson Zhang
 * @Date 2018/08/21
 * @desc 通用响应
 */
@Data
public class GeneralResponse {

    private String code;

    private String msg;

    private T data;

    public static  GeneralResponse failedResponse(String failedString) {
        GeneralResponse response = new GeneralResponse();
        response.setMsg(failedString);
        return response;
    }

    public static  GeneralResponse successfulResponse(String successfulString) {
        GeneralResponse response = new GeneralResponse();
        response.setMsg(successfulString);
        return response;
    }

}

第三步用postman测试接口情况

SpringBoot2.0.4使用JPA和Redis_第5张图片

多次调用http://localhost:8080/stu/getInfo,可以看到第一次获取学生张三的信息通过mysql数据库,后面的都是从redis中取出的数据,这里最好设置一个过期时间。

SpringBoot2.0.4使用JPA和Redis_第6张图片

调用http://localhost:8080/stu/findBySepc,可以获取姓张的所有学生的分页显示结果,表中只有一个。

总结:

1、redis想要实现对象的缓存,RedisConfig配置一定得配上,并且实体类要可序列化

2、springboot JPA简单查询持久层代码真的太简单

3、如果使用springboot JPA的新增,那么表不用自己建的

你可能感兴趣的:(Java技术)