JPA是Java Persistence API的简称,Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

它是SUN公司推出的一套基于ORM的规范。ORM又是什么?全英文名为Object-Relational Mapping:对象关系映射,简单来说为了不用JDBC那一套原始方法来操作数据库,ORM框架横空出世。

简单介绍下,Spring中的Spring-data-jpa技术,Spring Data JPA 是 Spring Data 系列的一部分,可以轻松实现基于 JPA 的存储库。该模块在处理对基于 JPA 的数据访问层的有所增强。使用数据访问技术快速构建应用变得更加容易。

特征:

  • 支持基于spring和JPA构建存储数据业务
  • 支持基于实体映射的XML
  • 提供使用原生sql能力的@Query注解
  • 分页支持、动态查询

本文的目录结构:



表示层:controller

业务层:Entity、Service、Vo

数据访问层:Repository

下面,我们通过一个完整地项目来展现JPA地能力:

1、创建数据库和表:

我们使用Navicat for MySQL工具,执行建表语句,创建一个student表

student建表语句
CREATE TABLE `student` (
`student_id` varchar(50) NOT NULL,
`name` varchar(50) NOT NULL DEFAULT 'cavan',
`classroom` varchar(50) NOT NULL DEFAULT '0',
`sex` varchar(10) NOT NULL DEFAULT '',
`email` varchar(50) NOT NULL,
`phone` varchar(20) NOT NULL DEFAULT '',
`created_by` varchar(20) NOT NULL DEFAULT 'cavan',
`last_modified_by` varchar(20) NOT NULL DEFAULT 'cavan',
`last_modified_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`created_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`student_id`),
UNIQUE KEY (`email`,`phone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

查看创建后的表:

2、引入依赖包

pom.xml的配置信息

pom.xml
        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency> <dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.1.14</version>
</dependency>
3、配置application.properties连接数据库信息
application.properties
# 应用名称
spring.application.name=jpa
# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据源名称
spring.datasource.name=defaultDataSource
# 数据库连接地址
spring.datasource.url=jdbc:mysql://121.43.225.17:3306/test?serverTimezone=UTC
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=
# 应用服务 WEB 访问端口
server.port=8888
4、业务层
4.1 定义entity实体类(StudentEntity类)
StudentEntity类
package com.cavan.jpa.entity;

import org.hibernate.annotations.Generated;
import org.hibernate.annotations.GenerationTime;
import org.hibernate.annotations.GenericGenerator; import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table; import java.sql.Timestamp; /**
* @program: jpa
* @description: <description>
* @author: cavan
* @create: 2021-12-03 20:44
*/
@Entity
@Table(name = "student")
@GenericGenerator(name = "uuid", strategy = "uuid")
public class StudentEntity {
private String id;
private String name;
private String classroom;
private String sex;
private String email;
private String phone;
private String createdBy;
private String lastModifiedBy;
private Timestamp lastModifiedDate;
private Timestamp createdDate; @Id
@GeneratedValue(generator = "uuid")
@Column(name = "student_id")
public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getClassroom() {
return classroom;
} public void setClassroom(String classroom) {
this.classroom = classroom;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
} public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
} public String getPhone() {
return phone;
} public void setPhone(String phone) {
this.phone = phone;
} public String getCreatedBy() {
return createdBy;
} public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
} public String getLastModifiedBy() {
return lastModifiedBy;
} public void setLastModifiedBy(String lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
} @Column(name = "last_modified_date",
columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP",
insertable = false,
updatable = false)
@Generated(GenerationTime.ALWAYS)
public Timestamp getLastModifiedDate() {
return lastModifiedDate;
} public void setLastModifiedDate(Timestamp lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
} @Column(name = "created_date",
columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP",
insertable = false,
updatable = false)
@Generated(GenerationTime.ALWAYS)
public Timestamp getCreatedDate() {
return createdDate;
} public void setCreatedDate(Timestamp createdDate) {
this.createdDate = createdDate;
}
}

一些常用注解(本文用到不多):

注解 作用 常用属性
@Entity 指定当前类是实体类
@Table 指定实体类和表之间的对应关系 name:指定数据库表的名称
@EntityListeners 在实体类增删改的时候监听,为创建人/创建时间等基础字段赋值 value:指定监听类
@Id 指定当前字段是主键
@SequenceGenerator 指定数据库序列别名 sequenceName:数据库序列名,name:取的别名
@GeneratedValue 指定主键的生成方式 strategy :指定主键生成策略 generator:选择主键别名
@Column 指定实体类属性和数据库表之间的对应关系 name:指定数据库表的列名称, unique:是否唯一, nullable:是否可以为空,nserttable:是否可以插入,updateable:是否可以更新,columnDefinition: 定义建表时创建此列的DDL
@CreatedBy 自动插入创建人
@CreatedDate 自动插入创建时间
@LastModifiedBy 自动修改更新人
@LastModifiedDate 自动修改更新时间
@JsonFormat 插入/修改/读取的时间转换成想要的格式 pattern:展示格式,timezone:国际时间

注意:

有了@EntityListeners(AuditingEntityListener.class)这个注解,@CreatedBy、@CreatedDate 、@LastModifiedBy 、@LastModifiedDate才生效哦,而且创建人和更新人需要另作注入操作。

4.2 Vo请求/响应类

由于我们在进行增删改查操作时所需要的请求入参信息是不一样的,接口响应需要返回的信息也不太一样,所以我们定义了不同的请求类,用以接收请求消息,传递给业务使用。这里我们分别定义了StudentVo类(创建、更新使用)、StudentIdVo类(删除使用)、StudentQueryVo类(查询使用)。

实际上,当你严格校验你的请求参数时,创建和更新请求类应该创建两个类加以区分,这个在请求入参校验实践会详细讲解。

创建更新请求Vo类:

StudentVo类
package com.cavan.jpa.vo;

/**
* @program: jpa
* @description: <description>
* @author: cavan
* @create: 2021-12-03 22:02
*/
public class StudentVo {
private String id;
private String name;
private String classroom;
private String sex;
private String email;
private String phone;
private String createdBy;
private String lastModifiedBy; public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getClassroom() {
return classroom;
} public void setClassroom(String classroom) {
this.classroom = classroom;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
} public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
} public String getPhone() {
return phone;
} public void setPhone(String phone) {
this.phone = phone;
} public String getCreatedBy() {
return createdBy;
} public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
} public String getLastModifiedBy() {
return lastModifiedBy;
} public void setLastModifiedBy(String lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
}
}

删除请求类:

StudentIdVo类
package com.cavan.jpa.vo;

/**
* @program: jpa
* @description: <description>
* @author: cavan
* @create: 2021-12-04 11:55
*/
public class StudentIdVo {
private String id; public String getId() {
return id;
} public void setId(String id) {
this.id = id;
}
}

查询请求类:

StudentQueryVo类
package com.cavan.jpa.vo;

/**
* @program: jpa
* @description: <description>
* @author: cavan
* @create: 2021-12-05 11:25
*/
public class StudentQueryVo {
private Integer pagesize;
private Integer pageNum;
private String id;
private String name;
private String classroom;
private String sex; public Integer getPagesize() {
return pagesize;
} public void setPagesize(Integer pagesize) {
this.pagesize = pagesize;
} public Integer getPageNum() {
return pageNum;
} public void setPageNum(Integer pageNum) {
this.pageNum = pageNum;
} public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getClassroom() {
return classroom;
} public void setClassroom(String classroom) {
this.classroom = classroom;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
}
}
4.3 service服务类(分为 StudentService 服务接口类和 StudentServiceImpl 服务实现类)

业务逻辑层的核心就是service服务及其实现类,一些重要的逻辑都会写到impl中,而不是直接写在controller中。

我们对学生实现最简单的新增、删除、修改、查询功能。

代码如下:

服务接口类:

StudentService类
package com.cavan.jpa.service;

import com.cavan.jpa.entity.StudentEntity;
import com.cavan.jpa.vo.StudentIdVo;
import com.cavan.jpa.vo.StudentQueryVo;
import com.cavan.jpa.vo.StudentVo; import java.util.List; public interface StudentService {
/**
* create student
*
* @return student
*/
String create(StudentVo studentVo); /**
* delete student
*
* @return student
*/
String delete(StudentIdVo studentIdVo); /**
* update student
*
* @return student
*/
String update(StudentVo studentVo); /**
* query student
*
* @return student
*/
List<StudentEntity> query(StudentQueryVo studentQueryVo); }

服务实现类:

StudentServiceImpl类
package com.cavan.jpa.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.cavan.jpa.entity.StudentEntity;
import com.cavan.jpa.repository.StudentRepository;
import com.cavan.jpa.service.StudentService;
import com.cavan.jpa.vo.StudentIdVo;
import com.cavan.jpa.vo.StudentQueryVo;
import com.cavan.jpa.vo.StudentVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList;
import java.util.List; /**
* @program: jpa
* @description: <description>
* @author: cavan
* @create: 2021-12-03 21:37
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentRepository studentRepository; @Override
public String create(StudentVo studentVo) {
StudentEntity studentEntity = new StudentEntity();
BeanUtils.copyProperties(studentVo, studentEntity);
studentRepository.save(studentEntity);
return "create ok";
} @Override
public String delete(StudentIdVo studentIdVo) {
studentRepository.deleteById(studentIdVo.getId());
return "delete ok";
} @Override
public String update(StudentVo studentVo) {
StudentEntity studentEntity = studentRepository.findById(studentVo.getId()).get();
BeanUtil.copyProperties(studentVo, studentEntity, true,
CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
studentRepository.save(studentEntity);
return "update ok";
} @Override
public List<StudentEntity> query(StudentQueryVo studentQueryVo) {
Integer pageNum = studentQueryVo.getPageNum();
List<Sort.Order> orders = new ArrayList<>();
orders.add(new Sort.Order(Sort.Direction.DESC, "last_modified_date"));
Sort sort = Sort.by(orders);
Pageable pageable = PageRequest.of(pageNum > 0 ? pageNum - 1 : pageNum, studentQueryVo.getPagesize(), sort);
Page<StudentEntity> page = studentRepository.queryStudent(studentQueryVo.getId(),
studentQueryVo.getName(),
studentQueryVo.getSex(),
studentQueryVo.getClassroom(), pageable);
if (page.getTotalPages() < pageNum && page.getTotalPages() > 0) {
page = studentRepository.queryStudent(studentQueryVo.getId(),
studentQueryVo.getName(),
studentQueryVo.getSex(),
studentQueryVo.getClassroom(), pageable);
}
return page.getContent();
}
}
5、表示层

我们这里全部使用的是POST请求,分别定义了以下功能接口:

  • 创建接口,用来创建一条学生信息数据
  • 删除接口,根据学生的学号删除学生信息
  • 更新接口,根据学生的学号更新学生信息
  • 查询接口,根据学生姓名、性别、班级等进行查询操作
StudentManageController类
package com.cavan.jpa.controller;

import com.cavan.jpa.entity.StudentEntity;
import com.cavan.jpa.service.StudentService;
import com.cavan.jpa.vo.StudentIdVo;
import com.cavan.jpa.vo.StudentQueryVo;
import com.cavan.jpa.vo.StudentVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import java.util.List; /**
* @program: jpa
* @description: <description>
* @author: cavan
* @create: 2021-12-03 20:22
*/
@RestController
@RequestMapping("/student")
public class StudentManageController {
@Autowired
private StudentService service; /**
* 创建学生
*
* @param studentVo 学生信息
* @return create OK
*/
@PostMapping("/create")
public String create(@RequestBody StudentVo studentVo) {
return service.create(studentVo);
} /**
* 根据学生的学号删除学生信息
*
* @param studentIdVo 学号
* @return delete OK
*/
@PostMapping("/delete")
public String delete(@RequestBody StudentIdVo studentIdVo) {
return service.delete(studentIdVo);
} /**
* 根据学生的学号更新学生信息
*
* @param studentVo 学号
* @return update OK
*/
@PostMapping("/update")
public String update(@RequestBody StudentVo studentVo) {
return service.update(studentVo);
} /**
* 根据学生姓名、性别、班级等查询
*
* @return query OK
*/
@PostMapping("/query")
public List<StudentEntity> query(@RequestBody StudentQueryVo studentQueryVo) {
return service.query(studentQueryVo);
}
}
6、数据连接层

这里只定义了原生sql的查询方法,其他基本的增删改查操作使用JPA内部提供的即可,只用继承 JpaRepository,不需要另外声明。

StudentRepository接口
package com.cavan.jpa.repository;

import com.cavan.jpa.entity.StudentEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository; @Repository
public interface StudentRepository extends JpaRepository<StudentEntity, String> {
/**
* query
*/
@Query(value = "select * from student where IF(ifnull(?1,'')!='',student_id=?1,1=1) " +
"and IF(ifnull(?2,'')!='',name like CONCAT('%',?2,'%'),1=1) " +
"and IF(ifnull(?3,'')!='',sex like CONCAT('%',?3,'%'),1=1) " +
"and IF(ifnull(?4,'')!='',classroom like CONCAT('%',?4,'%'),1=1)",
countQuery = "select count(1) from student where IF(ifnull(?1,'')!='',student_id=?1,1=1) " +
"and IF(ifnull(?2,'')!='',name like CONCAT('%',?2,'%'),1=1) " +
"and IF(ifnull(?3,'')!='',sex like CONCAT('%',?3,'%'),1=1) " +
"and IF(ifnull(?4,'')!='',classroom like CONCAT('%',?4,'%'),1=1)", nativeQuery = true)
Page<StudentEntity> queryStudent(String id, String name, String sex, String classroom, Pageable pageable);
}

问题记录:

(1)第一个问题

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.

2021-12-03 22:42:34.389 ERROR 15628 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :


APPLICATION FAILED TO START


Description:

Field service in com.cavan.jpa.controller.StudentManageController required a bean of type 'com.cavan.jpa.service.StudentService' that could not be found.

The injection point has the following annotations:

- @org.springframework.beans.factory.annotation.Autowired(required=true)

Action:

Consider defining a bean of type 'com.cavan.jpa.service.StudentService' in your configuration.

问题分析:

此问题是由于我在使用注解时错误的将

@Service

@Transactional(rollbackFor = Exception.class)

这两个注解放在了StudentService接口类上,实际应该定义在实现类上。

(2)第二个问题

2021-12-03 23:10:39.864 ERROR 15240 --- [nio-8888-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Unknown column 'created_by' in 'field list'

2021-12-03 23:10:39.917 ERROR 15240 --- [nio-8888-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement] with root cause

java.sql.SQLSyntaxErrorException: Unknown column 'created_by' in 'field list'

at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120) ~[mysql-connector-java-8.0.22.jar:8.0.22]

问题分析:

在使用建表语句时,我们创建的Entity实体类中的createdBy字段,映射到数据时会自动识别小驼峰,将其对应成created_by字段,所以建表时,我们要使用下划线方式,创建字段。

错误建表字段:

(3)第三个问题

2021-12-03 23:21:02.685 ERROR 14972 --- [nio-8888-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : Column 'classroom' cannot be null

2021-12-03 23:21:02.744 ERROR 14972 --- [nio-8888-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause

java.sql.SQLIntegrityConstraintViolationException: Column 'classroom' cannot be null

at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117) ~[mysql-connector-java-8.0.22.jar:8.0.22]

问题分析:

未在请求参数前加 @RequestBody 注解导致请求传过去的参数都为null值

(4)第四个问题

java.sql.SQLSyntaxErrorException: FUNCTION test.count does not exist. Check the 'Function Name Parsi

问题分析:

在使用原生sql的时候,多打了一个空格,导致报错。在使用原生sql这里最容易出错,可以通过在Navicat本地来测试语句的正确性。

本文代码Gitee链接:

https://gitee.com/cavan2021/springboot/tree/master/jpa

SpringBoot系列(七) jpa的使用,以增删改查为例的更多相关文章

  1. springboot+layui实现PC端用户的增删改查 & 整合mui实现app端的自动登录和用户的上拉加载 & HBuilder打包app并在手机端下载安装

    springboot整合web开发的各个组件在前面已经有详细的介绍,下面是用springboot整合layui实现了基本的增删改查. 同时在学习mui开发app,也就用mui实现了一个简单的自动登录和 ...

  2. 最简单的mybatis增删改查样例

    最简单的mybatis增删改查样例 Book.java package com.bookstore.app; import java.io.Serializable; public class Boo ...

  3. 基于SpringBoot开发一个Restful服务,实现增删改查功能

    前言 在去年的时候,在各种渠道中略微的了解了SpringBoot,在开发web项目的时候是如何的方便.快捷.但是当时并没有认真的去学习下,毕竟感觉自己在Struts和SpringMVC都用得不太熟练. ...

  4. spring boot快速入门 4: jpa数据库操作 实现增删改查

    spring boot jpa逆向生成表 简单实例: 第一步:pom文件: <?xml version="1.0" encoding="UTF-8"?&g ...

  5. oracle学习笔记系列------oracle 基本操作之表的增删改查

    --创建一个表 CREATE TABLE employee_souvc( id ), name ), gender ), birth DATE, salary ,), job ), deptno ) ...

  6. springboot+thymeleaf+springbootJPA实现一个简单的增删改查

    1.springboot是什么,给我们带来了什么方便? 通过阅读springboot的书籍发现springboot最便利的是为我们自动配置了很多的东西,几乎可以实现无xml,甚至简单的无sql,为我们 ...

  7. JPA+Hibernate 3.3 ——增删改查

    1.     查找对象   1)  用find()方法查找对象 public void getPerson(){ EntityManagerFactory factory = Persistence. ...

  8. (五)JPA - 原生SQL实现增删改查

    6.原生SQL JPA除了对JPQL提供支持外,还对原生SQL语句也提供了支持.下面小节一起来看看吧. 6.1 查询单个 示例代码: @Test public void getSingle() { E ...

  9. JavaWeb学习记录(七)——MVC操作数据库增删改查与分页功能

    一.分页工具类 package blank.util;import java.util.List; import org.springframework.jdbc.core.JdbcTemplate; ...

  10. Aerospike系列:4:简单的增删改查aql

    [root@localhost bin]# aql --help Usage: aql OPTIONS OPTIONS -h <host> The hostname to the serv ...

随机推荐

  1. 【全观测系列】Elasticsearch应用性能监控最佳实践

    ​简介:本文介绍了应用性能监控的应用价值以及解决方案等. 1.什么是全观测? 要了解全观测,我们先看看传统运维存在哪些问题. 数据孤岛,分散在不同部门,分析排查故障困难: 多个厂商的多种工具,无法自动 ...

  2. [FE] Js DOM 操作的几个常见错误

    1.setTimeout 匿名函数传参问题,匿名函数形参是不能直接在内部使用的,匿名函数传参需要按顺序从 setTimeout 的第三个参数开始依次传递. 2. Js clone出来的 dom 节点, ...

  3. WPF 使用 ManipulationDemo 工具辅助调试设备触摸失效问题

    本文将和大家介绍我所在的团队开源的 ManipulationDemo 工具.通过 ManipulationDemo 工具可以提升调试设备触摸失效的效率 此工具在 GitHub 上完全开源,请看 htt ...

  4. dotnet 7 已知问题 WPF 的 TreeView 开启虚拟化之后只显示首项

    本文记录 WPF 在 dotnet 7 的一个已知问题,此问题当前已修复,只需更新 SDK 或运行时即可.使用 TreeView 在开启虚拟化之后只显示首项,其他项不显示.本文将告诉大家此问题的原因和 ...

  5. 学会使用 NumPy:基础、随机、ufunc 和练习测试

    NumPy NumPy 是一个用于处理数组的 Python 库.它代表"Numerical Python". 基本 随机 ufunc 通过测验测试学习 检验您对 NumPy 的掌握 ...

  6. (更新中)gprMax项目代码分解:gprMax.constants.py、gprMax.exceptions

    目录 1. 引言 2. gprMax.constants.py 3. gprMax.exceptions.py 4. 总结 Reference 1. 引言 本文对gprMax项目中的"gpr ...

  7. homebrew的安装和使用

    目录 背景 安装xcode 安装homebrew 有关报错解决 卸载脚本 homebrew软件搜索 brew 常用命令 brew redis安装 PhpWebStudy安装 安装php 背景 最近用b ...

  8. Python中强大的通用ORM框架:SQLAlchemy

    Python中强大的通用ORM框架:SQLAlchemy https://zhuanlan.zhihu.com/p/444930067

  9. go-admin开发小技巧

    搜索条件参考下面的文件 https://github.com/go-admin-team/go-admin-core/blob/master/tools/search/query_test.go ty ...

  10. spring-boot集成Quartz-job存储方式二RAM

    简单区分: RAM:程序启动从数据库中读取原始job配置(也可以从配置文件中读取),job中间运行过程在RAM内存中,程序停止或重启后,RAM中数据丢失,再次启动的时候会重新读取job配置.适合于单机 ...