美文网首页Spring全家桶实践
Spring全家桶实践-数据操作JPA

Spring全家桶实践-数据操作JPA

作者: 一块自由的砖 | 来源:发表于2019-08-02 16:41 被阅读0次

    知识贮备

    Spring Data JPA官方网站
    JPA规范与ORM框架之间的关系
    Spring Data JPA与JPA规范的关系
    Spring Data JPA中常用的注解

    实践过程

    目标:实现AOP日志记录到数据库中

    数据用户权限设置,需要有创建表的权利,这里把库的权限都先给springsaas用户

        grant all privileges on springsaas.* to springsaas@'10.1.60.%' identified by 'springsaas';
        flush privileges;
    

    引入依赖包

            <!-- Spring Data JPA的相关依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <!-- 用于连接mysql的相关依赖 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <!-- 数据库连接池(dbcp2),以后用阿里的druid相关依赖 -->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-dbcp2</artifactId>
            </dependency>
    

    配置application.properties 新增数据库,连接池,JPA配置

    说明:

    • com.mysql.jdbc.Driver已经废弃了,使用新的com.mysql.cj.jdbc.Driver
    • spring.datasource.url username password 根据实际情况自行设置
    • 连接池有很多,例如:c3p0,hikari,druid,dbcp2等等,本次使用的是dbcp2
    #项目相关配置
    server.port=8080
    #服务名称
    spring.application.name=springsaas
    #数据库配置
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/springsaas?characterEncoding=UTF-8
    spring.datasource.username=springsaas
    spring.datasource.password=springsaas
    ##设置使用那个连接池
    spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource
    #DBCP2配置(连接池)
    ##初始化连接池idle数量
    spring.datasouece.dbcp2.initial-size=10
    ##连接最小idle数量
    spring.datasource.dbcp2.min-idle=10
    ##连接最大idle数量
    spring.datasource.dbcp2.max-idle=30
    ##连接超时的等待时间(30秒)
    spring.datasource.dbcp2.max-wait-millis=30000
    ##轮询间隔时间,检测需要关闭的数据库连接 3分钟
    spring.datasource.dbcp2.time-between-eviction-runs-millis=180000
    #配置jpa
    ##配置数据库类型
    spring.jpa.database=mysql
    ##配置是否输出sql语句
    spring.jpa.show-sql=true
    ##ddl方式
    #1、create:启动时删除上一次生成的表,并根据实体类生成表,表中数据会被清空。
    #2、create-drop:启动时根据实体类生成表,sessionFactory关闭时表会被删除。
    #3、update:启动时会根据实体类生成表,当实体类属性变动的时候,表结构也会更新,在初期开发阶段使用此选项。
    #4、validate:启动时验证实体类和数据表是否一致,在我们数据结构稳定时采用此选项。
    #5、none:不采取任何措施。
    spring.jpa.hibernate.ddl-auto=update
    
    #让控制器输出的json字符串格式更美观。
    spring.jackson.serialization.indent-output=true
    

    目录结构

    logging目录结构

    实现源码

    改造domain 实体类(bean)和数据表进行映射,并且配置好映射关系,粗浅的类比为pojo

    package com.springboot.action.saas.common.logging.domain;
    
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import org.hibernate.annotations.CreationTimestamp;
    
    import javax.persistence.*;
    import java.sql.Timestamp;
    /*
    * 日志数据和数据表实体类
    * */
    @Data
    //jpa 实体
    @Entity
    //表名
    @Table(name="mkt_log")
    //lombok 注解,NoArgsConstructor 无参数构造函数
    @NoArgsConstructor
    public class Log {
        //设置ID主键,定义生成策略为自增
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        //描述
        private String description;
        //方法名
        private String method;
        //参数,定义字段类型为text
        @Column(columnDefinition = "text")
        private String params;
        //日志类型, 定义字段名称
        @Column(name = "log_type")
        private String logType;
        //请求ip, 定义字段名称
        @Column(name = "request_ip")
        private String requestIp;
        //请求耗时
        private Long time;
        //异常详细,定义字段名称
        @Column(name = "exception_detail", columnDefinition = "text")
        private String exceptionDetail;
        //请求时间,实体插入数据库的时候设置这个数值
        @CreationTimestamp
        @Column(name = "create_time")
        private Timestamp createTime;
        //构造函数(代参)
        public Log(String logType, Long time) {
            this.logType = logType;
            this.time = time;
        }
    }
    

    新建Repository 接口来操作实体类对应的数据表,粗浅的理解为Dao

    package com.springboot.action.saas.common.logging.repository;
    
    import com.springboot.action.saas.common.logging.domain.Log;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
    import org.springframework.stereotype.Repository;
    
    /*
    * JpaRepository继承了接口PagingAndSortingRepository和QueryByExampleExecutor。
    * PagingAndSortingRepository又继承CrudRepository。
    * JpaRepository接口同时拥有基本CRUD功能以及分页功能。
    * 官方的给的定义
    * public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T>
    * T 实例类
    * ID id的数据类型
    * */
    @Repository
    public interface LogRepository extends JpaRepository<Log,Long> {
    }
    

    改造service impl,在上一个tag版本里面增加了记录数据库的功能

    增加私有成员变量 logRepository
    逻辑增加日志记录到数据库 logRepository.save(log);

    package com.springboot.action.saas.common.logging.service.impl;
    
    import com.springboot.action.saas.common.logging.domain.Log;
    import com.springboot.action.saas.common.logging.repository.LogRepository;
    import com.springboot.action.saas.common.logging.service.LogService;
    import com.springboot.action.saas.common.utils.StringUtils;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    import java.lang.reflect.Method;
    
    @Service
    public class LogServiceImpl implements LogService {
        //数据操作类,相当于DAO
        @Autowired
        private LogRepository logRepository;
    
        /*
        * 记录日志接口实现
        **/
        @Override
        public void save(ProceedingJoinPoint joinPoint, Log log) {
            //获取request 请求对象
            HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes())
                    .getRequest();
            //getSignature获取切面相关信息,比如方法名、目标方法参数等信息
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            //获取抽象类(代理对象)方法
            Method method = signature.getMethod();
            //返回该元素的指定类型的注释,这里是Log注解
            com.springboot.action.saas.common.logging.annotation.Log aopLog = method.getAnnotation(com.springboot.action.saas.common.logging.annotation.Log.class);
            //获取注解传递的参数
            if (log != null) {
                log.setDescription(aopLog.value());
            }
            //通过最笨的反射方法,获取方法路径
            String methodName = joinPoint.getTarget().getClass().getName()+"."+signature.getName()+"()";
            log.setMethod(methodName);
            //参数处理
            //获取参数值
            Object[] argValues = joinPoint.getArgs();
            //获取参数名
            String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
            //组织参数列表
            String params = "{";
            if(argValues != null){
                for (int i = 0; i < argValues.length; i++) {
                    params += " " + argNames[i] + ": " + argValues[i];
                }
            }
            log.setParams(params + " }");
            //获取IP地址
            log.setRequestIp(StringUtils.getIP(request));
            //输出日志到控制台
            System.out.println(log.toString());
            //日志记录到数据库
            logRepository.save(log);
        }
    }
    

    运行测试效果

    控制台输出sql,启动会创建表

    Using dialect: org.hibernate.dialect.MySQL5Dialect
    Hibernate: create table mkt_log (id bigint not null auto_increment, create_time datetime, description varchar(255), exception_detail text, log_type varchar(255), method varchar(255), params text, request_ip varchar(255), time bigint, primary key (id)) engine=MyISAM
    

    数据库springsaas会创建mkt_log,当有自定义@Log注解的接口被访问请求后,表就会插入一条数据。

    打标签

    打tag 1.0.5版本,提交代码。

    git tag -a v1.0.5 -m "实现日志信息通过JPA记录到数据库"

    git push origin v1.0.5

    github地址:https://github.com/horacepei/springsaas

    相关文章

      网友评论

        本文标题:Spring全家桶实践-数据操作JPA

        本文链接:https://www.haomeiwen.com/subject/vorqdctx.html