Commit 60976805 authored by 宋欢's avatar 宋欢

Initial commit

parents
# Treat all files in this repo as binary, with no git magic updating
# line endings. Windows users contributing to Go will need to use a
# modern version of git and editors capable of LF line endings.
#
# We'll prevent accidental CRLF line endings from entering the repo
# via the git-review gofmt checks.
#
# See golang.org/issue/9281
* -text
# Concourse
concourse/credentials.yml
# Misc
*~
.#*
dependency-reduced-pom.xml
.DS_Store
data/
tmp/
*.sw[op]
*.class
classes/
test.log
*.log
logs/
work/
.bower-*
lib/
dist/
*.tar.gz
# Eclipse
# > the following should be created by `./gradlew eclipse`
.classpath
.project
# > ignore all eclipse settings by default
.settings
# > except the following, primarily for formatting purposes
!.settings/org.eclipse.jdt.core.prefs
!.settings/org.eclipse.jdt.ui.prefs
!.settings/org.eclipse.wst.html.core.prefs
# > other misc eclipse artifacts
.springBeans
bin
atlassian-ide-plugin.xml
# IDEA
.idea
*.iml
*.ipr
*.iws
out
# Gradle
.gradle
build
/build
/target
# Structure101
japp.java.hsp
# jspm
jspm_packages/
npm-debug.log
.cram/
MySQL的操作,离不开Laravel-DB和Model,简单一句话,DB::table('user')->where('id', 1)->first();
Java也有类似Laravel-DB的ORM框架,之前流行Hibernate,现在我们用MyBatis
# mybatis-demo
MyBatis 简单示例
http://127.0.0.1:8080/swagger-ui.html
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>demo-biz</artifactId>
<version>1.0.1.SNAPSHOT</version>
<parent>
<groupId>cn.qmai.study.java.demo</groupId>
<artifactId>mybatis-demo</artifactId>
<version>1.0.1.SNAPSHOT</version>
</parent>
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<!-- 在控制台打印执行日志 -->
<verbose>true</verbose>
<!-- 重复生成时会覆盖之前的文件 -->
<overwrite>true</overwrite>
<configurationFile>src/main/generator/mybatis.xml</configurationFile>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="MySqlTables" targetRuntime="MyBatis3">
<!--数据库连接的信息:驱动类、连接、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=Asia/Shanghai"
userId="root"
password="123456">
</jdbcConnection>
<!-- 默认 false,把 JDBC DECIMAL 和 NUMERIC 类型解析为 Integer;为 true 时,把 JDBC DECIMAL 和 NUMERIC 类型解析为 java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- 生成实体类的包名和位置 -->
<javaModelGenerator targetPackage="cn.qmai.study.java.demo.biz.model" targetProject="src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- 生成的xml映射文件包名和位置 -->
<sqlMapGenerator targetPackage="mappings" targetProject="src/main/resources">
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
<!-- 生成mapper的包名和位置 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="cn.qmai.study.java.demo.biz.dao"
targetProject="src/main/java">
<property name="enableSubPackages" value="false"/>
</javaClientGenerator>
<table tableName="user" domainObjectName="User"/>
</context>
</generatorConfiguration>
package cn.qmai.study.java.demo.biz.dao;
import cn.qmai.study.java.demo.biz.model.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 用户
*
* @author 宋欢
*/
public interface UserMapper {
/**
* 查询列表
*
* @param record User
* @param beginId 开始的主键(结果集中不包含该主键)
* @param pageSize 每页条数
* @return list
*/
List<User> findList(@Param("record") User record, @Param("beginId") long beginId, @Param("pageSize") int pageSize);
/**
* 查询总数,Count
*
* @param record User
* @return long
*/
long getTotalNum(@Param("record") User record);
/**
* 通过主键,获取一条记录
*
* @param id 主键
* @return User
*/
User find(@Param("id") long id);
/**
* 新增多条记录
*
* @param list User
* @return 影响行数
*/
long insertList(@Param("list") List<User> list);
/**
* 新增一条记录
*
* @param record User
* @return 影响行数
*/
int insert(User record);
/**
* 通过主键,修改多条记录
*
* @param list User
* @return 影响行数
*/
long updateList(@Param("list") List<User> list);
/**
* 通过主键,修改一条记录
*
* @param record User
* @return 影响行数
*/
int update(User record);
}
package cn.qmai.study.java.demo.biz.interceptor;
import com.google.common.base.Preconditions;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Properties;
/**
* Mybatis Executor类 拦截器
* <pre>
* mybatis.xml
* <configuration>
* <plugins>
* <plugin interceptor="cn.qmai.study.java.demo.biz.interceptor.ExecutorInterceptor">
* <property name="databaseType" value="mysql"/>
* </plugin>
* </plugins>
* </configuration>
* </pre>
*
* @author 宋欢
*/
@Intercepts({
@Signature(
type = Executor.class,
method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
),
@Signature(
type = Executor.class,
method = "update",
args = {MappedStatement.class, Object.class}
)
})
public class ExecutorInterceptor implements Interceptor {
private static final Logger logger = LoggerFactory.getLogger(ExecutorInterceptor.class);
@Override
public Object intercept(Invocation invocation) throws Throwable {
Preconditions.checkNotNull(invocation, "invocation can't be null");
long beginAt = System.currentTimeMillis();
Object proceedResult = invocation.proceed();
long endAt = System.currentTimeMillis();
try {
LogWriter.write(invocation, beginAt, endAt);
} catch (Throwable tr) {
logger.error("Mybatis, writeLog failed, beginAt: {}, endAt: {}, throwable: ", beginAt, endAt, tr);
}
return proceedResult;
}
@Override
public Object plugin(Object target) {
if (target == null) {
return null;
}
if (target instanceof Executor) {
return Plugin.wrap(target, this);
}
return target;
}
@Override
public void setProperties(Properties properties) {
}
}
package cn.qmai.study.java.demo.biz.interceptor;
import com.alibaba.fastjson.JSON;
import java.io.Serializable;
import java.util.List;
/**
* 日志概要
*
* @author 宋欢
*/
public final class LogSchema implements Serializable {
/**
* 完整SQL,如:INSERT INTO table (id, name) VALUES (1, 'abc');
*/
private String sql;
/**
* 预处理SQL,如:INSERT INTO table (id, name) VALUES (?, ?);
*/
private String prepareSql;
/**
* 参数列表
*/
private List<Object> bindings;
/**
* 执行耗时,单位:毫秒
*/
private long elapsed;
/**
* 配置id
*/
private String databaseId;
@Override
public String toString() {
return JSON.toJSONString(this);
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
public String getPrepareSql() {
return prepareSql;
}
public void setPrepareSql(String prepareSql) {
this.prepareSql = prepareSql;
}
public List<Object> getBindings() {
return bindings;
}
public void setBindings(List<Object> bindings) {
this.bindings = bindings;
}
public long getElapsed() {
return elapsed;
}
public void setElapsed(long elapsed) {
this.elapsed = elapsed;
}
public String getDatabaseId() {
return databaseId;
}
public void setDatabaseId(String databaseId) {
this.databaseId = databaseId;
}
}
package cn.qmai.study.java.demo.biz.interceptor;
import com.google.common.base.Preconditions;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.session.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
/**
* 写日志
*
* @author 宋欢
*/
public final class LogWriter {
private static final Logger logger = LoggerFactory.getLogger(LogWriter.class);
/**
* 写日志
*
* @param invocation Invocation
* @param beginAt 开始执行时间
* @param endAt 结束执行时间
*/
public static void write(Invocation invocation, long beginAt, long endAt) {
Preconditions.checkNotNull(invocation, "invocation can't be null");
Object[] args = invocation.getArgs();
Preconditions.checkNotNull(args, "args can't be null");
Preconditions.checkArgument(args.length > 0, "args.length must be greater than 0");
Preconditions.checkNotNull(args[0], "args[0] can't be null");
MappedStatement statement = (MappedStatement) args[0];
Object parameterObject = args.length > 1 ? args[1] : null;
write(statement, parameterObject, beginAt, endAt);
}
/**
* 写日志
*
* @param statement MappedStatement
* @param parameterObject Object
* @param beginAt 开始执行时间
* @param endAt 结束执行时间
*/
public static void write(MappedStatement statement, Object parameterObject, long beginAt, long endAt) {
Preconditions.checkNotNull(statement, "statement can't be null");
String id = statement.getId();
BoundSql boundSql = statement.getBoundSql(parameterObject);
Configuration configuration = statement.getConfiguration();
LogSchema schema = getSchema(boundSql, configuration, beginAt, endAt);
logger.info("Mybatis, id: {}, beginAt: {}, endAt: {}, schema: {}", id, beginAt, endAt, schema);
}
/**
* 获取日志概要
*
* @param boundSql BoundSql
* @param configuration Configuration
* @param beginAt 开始执行时间
* @param endAt 结束执行时间
* @return LogSchema
*/
public static LogSchema getSchema(BoundSql boundSql, Configuration configuration, long beginAt, long endAt) {
Preconditions.checkNotNull(boundSql, "boundSql can't be null");
Preconditions.checkNotNull(configuration, "configuration can't be null");
String prepareSql = boundSql.getSql();
List<Object> bindings = SqlUtils.getBindings(boundSql, configuration);
long elapsed = endAt - beginAt;
String databaseId = configuration.getDatabaseId();
String sql = SqlUtils.replaceHolder(prepareSql, bindings);
LogSchema schema = new LogSchema();
schema.setSql(sql);
schema.setPrepareSql(prepareSql);
schema.setBindings(bindings);
schema.setElapsed(elapsed);
schema.setDatabaseId(databaseId);
return schema;
}
}
package cn.qmai.study.java.demo.biz.interceptor;
import com.google.common.base.Preconditions;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.springframework.util.StringUtils;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
/**
* 分析SQL
*
* @author 宋欢
*/
public final class SqlUtils {
/**
* Date格式
*/
private static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd HH:mm:ss";
/**
* 空白字符,如:空格、制表符、换页符等
*/
private static final String REGEX_SPACE = "[\\s]+";
/**
* 占位符
*/
private static final String PLACE_HOLDER = "\\?";
/**
* NULL填充占位符
*/
private static final String PLACE_NULL = "NULL";
private SqlUtils() {
}
/**
* 替换“预处理SQL”中所有占位符
*
* @param prepareSql 预处理SQL,如:INSERT INTO table (id, name) VALUES (?, ?);
* @param bindings 参数列表
* @return INSERT INTO table (id, name) VALUES (1, 'abc');
*/
public static String replaceHolder(String prepareSql, List<Object> bindings) {
String sql = trimSql(prepareSql);
if (StringUtils.isEmpty(sql) || StringUtils.isEmpty(bindings)) {
return sql;
}
for (Object value : bindings) {
String replacement = quoteValue(value);
replacement = Matcher.quoteReplacement(replacement);
sql = sql.replaceFirst(PLACE_HOLDER, replacement);
}
return sql;
}
/**
* 去掉SQL中所有重复的空白字符,包括:空格、制表符、换页符等
* 包括Value中的空白字符,建议仅用于“预处理SQL”,不影响Value
*
* @param prepareSql 预处理SQL,如:INSERT INTO table (id, name) VALUES (?, ?);\n
* @return INSERT INTO table (id, name) VALUES (?, ?);
*/
public static String trimSql(String prepareSql) {
return prepareSql != null ? prepareSql.replaceAll(REGEX_SPACE, " ") : null;
}
/**
* 引用参数,用于填充占位符
*
* @param value 参数,如:1, abc, null, 2020-01-01 08:00:00
* @return 1, 'abc', NULL, '2020-01-01 08:00:00'
*/
public static String quoteValue(Object value) {
if (value == null) {
return PLACE_NULL;
}
if (value instanceof String) {
return "'" + value + "'";
}
if (value instanceof Date) {
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_PATTERN);
return "'" + dateFormat.format(value) + "'";
}
return value.toString();
}
/**
* 参数列表
*
* @param boundSql BoundSql
* @param configuration Configuration
* @return Object List, or null
*/
public static List<Object> getBindings(BoundSql boundSql, Configuration configuration) {
Preconditions.checkNotNull(boundSql, "boundSql can't be null");
Preconditions.checkNotNull(configuration, "configuration can't be null");
List<ParameterMapping> parameterMappingList = boundSql.getParameterMappings();
if (parameterMappingList == null) {
return null;
}
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
Object parameterObject = boundSql.getParameterObject();
MetaObject metaObject = configuration.newMetaObject(parameterObject);
List<Object> bindings = new ArrayList<>();
for (ParameterMapping parameterMapping : parameterMappingList) {
if (parameterMapping == null) {
continue;
}
if (parameterMapping.getMode() == ParameterMode.OUT) {
continue;
}
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) {
Object parameter = boundSql.getAdditionalParameter(propertyName);
bindings.add(parameter);
continue;
}
if (parameterObject == null) {
bindings.add(null);
continue;
}
if (typeHandlerRegistry != null && typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
bindings.add(parameterObject);
continue;
}
if (metaObject != null) {
Object parameter = metaObject.getValue(propertyName);
bindings.add(parameter);
continue;
}
bindings.add(null);
}
return bindings;
}
}
package cn.qmai.study.java.demo.biz.model;
import com.alibaba.fastjson.JSON;
import java.io.Serializable;
import java.util.Date;
/**
* 用户
*
* @author 宋欢
*/
public final class User implements Serializable {
/**
* 用户id
*/
private Long id;
/**
* 手机号
*/
private String phone;
/**
* 姓名
*/
private String username;
/**
* 性别,0-未知、1-男性、2-女性、3-疑似男性、4-疑似女性
*/
private Integer gender;
/**
* 出生日,年-月-日,如:2006-01-02
*/
private Date birthday;
/**
* 邮箱
*/
private String email;
/**
* 有效?1-有效、0-无效
*/
private Integer isActive;
/**
* 备注
*/
private String remark;
/**
* 删除?id-是、0-否
*/
private Long isDeleted;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
/**
* 删除时间
*/
private Date deletedAt;
@Override
public String toString() {
return JSON.toJSONString(this);
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getIsActive() {
return isActive;
}
public void setIsActive(Integer isActive) {
this.isActive = isActive;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Long getIsDeleted() {
return isDeleted;
}
public void setIsDeleted(Long isDeleted) {
this.isDeleted = isDeleted;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public Date getDeletedAt() {
return deletedAt;
}
public void setDeletedAt(Date deletedAt) {
this.deletedAt = deletedAt;
}
}
package cn.qmai.study.java.demo.biz.service;
import cn.qmai.study.java.demo.biz.model.User;
import java.text.ParseException;
import java.util.List;
/**
* 用户
*
* @author 宋欢
*/
public interface UserService {
/**
* 查询列表
*
* @return list
*/
List<User> findList();
/**
* 查询总数,Count
*
* @return long
*/
long getTotalNum();
/**
* 通过主键,获取一条记录
*
* @return User
*/
User find();
/**
* 新增多条记录
*
* @return 影响行数
*/
long insertList() throws ParseException;
/**
* 新增一条记录
*
* @return 影响行数
*/
int insert() throws ParseException;
/**
* 通过主键,修改多条记录
*
* @return 影响行数
*/
long updateList();
/**
* 通过主键,修改一条记录
*
* @return 影响行数
*/
int update();
}
package cn.qmai.study.java.demo.biz.service.impl;
import cn.qmai.study.java.demo.biz.dao.UserMapper;
import cn.qmai.study.java.demo.biz.model.User;
import cn.qmai.study.java.demo.biz.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* @author 宋欢
*/
@Service
public class UserServiceImpl implements UserService {
private static final Random RANDOM = new Random();
@Autowired
private UserMapper mapper;
@Override
public List<User> findList() {
// 查询,“男性” 且 “有效”
User record = new User();
record.setGender(1);
record.setIsActive(1);
return mapper.findList(record, 0, 10);
}
@Override
public long getTotalNum() {
// 查询总数,“男性” 且 “有效”
User record = new User();
record.setGender(1);
record.setIsActive(1);
return mapper.getTotalNum(record);
}
@Override
public User find() {
// 获取,id = 1
return mapper.find(1L);
}
@Override
public long insertList() throws ParseException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
List<User> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
User record = new User();
record.setPhone(String.format("130%08d", RANDOM.nextInt(100000000)));
record.setUsername("张三-" + RANDOM.nextInt(10000));
record.setGender(RANDOM.nextInt(2));
record.setBirthday(dateFormat.parse(String.format("199%d-%02d-%02d", RANDOM.nextInt(10), RANDOM.nextInt(12) + 1, RANDOM.nextInt(28) + 1)));
record.setEmail(RANDOM.nextInt(10000) + "@qq.com");
record.setIsActive(RANDOM.nextInt(2));
record.setRemark("新增多条记录-" + RANDOM.nextInt(10000));
list.add(record);
}
return mapper.insertList(list);
}
@Override
public int insert() throws ParseException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
User record = new User();
record.setPhone(String.format("130%08d", RANDOM.nextInt(100000000)));
record.setUsername("张三-" + RANDOM.nextInt(10000));
record.setGender(RANDOM.nextInt(2));
record.setBirthday(dateFormat.parse(String.format("199%d-%02d-%02d", RANDOM.nextInt(10), RANDOM.nextInt(12) + 1, RANDOM.nextInt(28) + 1)));
record.setEmail(RANDOM.nextInt(10000) + "@qq.com");
record.setIsActive(RANDOM.nextInt(2));
record.setRemark("新增一条记录-" + RANDOM.nextInt(10000));
return mapper.insert(record);
}
@Override
public long updateList() {
List<User> list = new ArrayList<>();
for (long id = 2; id < 10; id++) {
User record = new User();
record.setId(id);
record.setUsername("王五-" + RANDOM.nextInt(10000));
record.setIsActive(RANDOM.nextInt(2));
record.setRemark("修改多条记录-" + RANDOM.nextInt(10000));
list.add(record);
}
return mapper.updateList(list);
}
@Override
public int update() {
User record = new User();
record.setId(1L);
record.setUsername("李四-" + RANDOM.nextInt(10000));
record.setGender(0);
record.setEmail(RANDOM.nextInt(10000) + "@163.com");
record.setIsActive(0);
record.setRemark("修改一条记录-" + RANDOM.nextInt(10000));
return mapper.update(record);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.qmai.study.java.demo.biz.dao.UserMapper">
<resultMap id="BaseResultMap" type="cn.qmai.study.java.demo.biz.model.User">
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="phone" jdbcType="VARCHAR" property="phone"/>
<result column="username" jdbcType="VARCHAR" property="username"/>
<result column="gender" jdbcType="INTEGER" property="gender"/>
<result column="birthday" jdbcType="DATE" property="birthday"/>
<result column="email" jdbcType="VARCHAR" property="email"/>
<result column="is_active" jdbcType="INTEGER" property="isActive"/>
<result column="remark" jdbcType="VARCHAR" property="remark"/>
<result column="is_deleted" jdbcType="BIGINT" property="isDeleted"/>
<result column="created_at" jdbcType="TIMESTAMP" property="createdAt"/>
<result column="updated_at" jdbcType="TIMESTAMP" property="updatedAt"/>
<result column="deleted_at" jdbcType="TIMESTAMP" property="deletedAt"/>
</resultMap>
<sql id="Base_Column_List">
id,
phone,
username,
gender,
birthday,
email,
is_active,
remark,
is_deleted,
created_at,
updated_at,
deleted_at
</sql>
<select id="findList" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List"/>
FROM user
<where>
<if test="record != null">
<if test="record.phone != null">
AND phone = #{record.phone,jdbcType=VARCHAR}
</if>
<if test="record.username != null">
AND username = #{record.username,jdbcType=VARCHAR}
</if>
<if test="record.gender != null">
AND gender = #{record.gender,jdbcType=INTEGER}
</if>
<if test="record.birthday != null">
AND birthday = #{record.birthday,jdbcType=DATE}
</if>
<if test="record.email != null">
AND email = #{record.email,jdbcType=VARCHAR}
</if>
<if test="record.isActive != null">
AND is_active = #{record.isActive,jdbcType=INTEGER}
</if>
<if test="record.remark != null">
AND remark = #{record.remark,jdbcType=VARCHAR}
</if>
</if>
AND is_deleted = 0
AND id <![CDATA[ > ]]> #{beginId,jdbcType=BIGINT}
</where>
ORDER BY created_at DESC
<if test="pageSize > 0">
LIMIT #{pageSize,jdbcType=INTEGER}
</if>
</select>
<select id="getTotalNum" resultType="long">
SELECT COUNT(*) AS aggregate
FROM user
<where>
<if test="record != null">
<if test="record.phone != null">
AND phone = #{record.phone,jdbcType=VARCHAR}
</if>
<if test="record.username != null">
AND username = #{record.username,jdbcType=VARCHAR}
</if>
<if test="record.gender != null">
AND gender = #{record.gender,jdbcType=INTEGER}
</if>
<if test="record.birthday != null">
AND birthday = #{record.birthday,jdbcType=DATE}
</if>
<if test="record.email != null">
AND email = #{record.email,jdbcType=VARCHAR}
</if>
<if test="record.isActive != null">
AND is_active = #{record.isActive,jdbcType=INTEGER}
</if>
<if test="record.remark != null">
AND remark = #{record.remark,jdbcType=VARCHAR}
</if>
</if>
AND is_deleted = 0
</where>
</select>
<select id="find" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List"/>
FROM user
<where>
AND id = #{id,jdbcType=BIGINT}
</where>
</select>
<insert id="insertList" parameterType="java.util.List">
INSERT INTO user
(phone,
username,
gender,
birthday,
email,
is_active,
remark,
is_deleted)
VALUES
<foreach collection="list" item="record" index="index" separator=",">
<if test="record != null">
(#{record.phone,jdbcType=VARCHAR},
#{record.username,jdbcType=VARCHAR},
#{record.gender,jdbcType=INTEGER},
#{record.birthday,jdbcType=DATE},
#{record.email,jdbcType=VARCHAR},
#{record.isActive,jdbcType=INTEGER},
#{record.remark,jdbcType=VARCHAR},
0)
</if>
</foreach>
</insert>
<insert id="insert" parameterType="cn.qmai.study.java.demo.biz.model.User">
INSERT INTO user
(phone,
username,
gender,
birthday,
email,
is_active,
remark,
is_deleted)
VALUES (#{phone,jdbcType=VARCHAR},
#{username,jdbcType=VARCHAR},
#{gender,jdbcType=INTEGER},
#{birthday,jdbcType=DATE},
#{email,jdbcType=VARCHAR},
#{isActive,jdbcType=INTEGER},
#{remark,jdbcType=VARCHAR},
0)
</insert>
<update id="updateList" parameterType="java.util.List">
<foreach collection="list" item="record" index="index" open="" close="" separator=";">
<if test="record != null">
UPDATE user
<set>
<if test="record.phone != null">
phone = #{record.phone,jdbcType=VARCHAR},
</if>
<if test="record.username != null">
username = #{record.username,jdbcType=VARCHAR},
</if>
<if test="record.gender != null">
gender = #{record.gender,jdbcType=INTEGER},
</if>
<if test="record.birthday != null">
birthday = #{record.birthday,jdbcType=DATE},
</if>
<if test="record.email != null">
email = #{record.email,jdbcType=VARCHAR},
</if>
<if test="record.isActive != null">
is_active = #{record.isActive,jdbcType=INTEGER},
</if>
<if test="record.remark != null">
remark = #{record.remark,jdbcType=VARCHAR},
</if>
<if test="record.isDeleted != null">
is_deleted = #{record.isDeleted,jdbcType=BIGINT},
</if>
<if test="record.deletedAt != null">
deleted_at = #{record.deletedAt,jdbcType=TIMESTAMP},
</if>
</set>
<where>
AND id = ${record.id}
</where>
</if>
</foreach>
</update>
<update id="update" parameterType="cn.qmai.study.java.demo.biz.model.User">
UPDATE user
<set>
<if test="phone != null">
phone = #{phone,jdbcType=VARCHAR},
</if>
<if test="username != null">
username = #{username,jdbcType=VARCHAR},
</if>
<if test="gender != null">
gender = #{gender,jdbcType=INTEGER},
</if>
<if test="birthday != null">
birthday = #{birthday,jdbcType=DATE},
</if>
<if test="email != null">
email = #{email,jdbcType=VARCHAR},
</if>
<if test="isActive != null">
is_active = #{isActive,jdbcType=INTEGER},
</if>
<if test="remark != null">
remark = #{remark,jdbcType=VARCHAR},
</if>
<if test="isDeleted != null">
is_deleted = #{isDeleted,jdbcType=BIGINT},
</if>
<if test="deletedAt != null">
deleted_at = #{deletedAt,jdbcType=TIMESTAMP},
</if>
</set>
<where>
AND id = #{id,jdbcType=BIGINT}
</where>
</update>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>demo-web</artifactId>
<version>1.0.1.SNAPSHOT</version>
<parent>
<groupId>cn.qmai.study.java.demo</groupId>
<artifactId>mybatis-demo</artifactId>
<version>1.0.1.SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>cn.qmai.study.java.demo</groupId>
<artifactId>demo-biz</artifactId>
<version>1.0.1.SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>
\ No newline at end of file
package cn.qmai.study.java.demo.web.api;
import cn.qmai.study.java.demo.biz.model.User;
import cn.qmai.study.java.demo.biz.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.text.ParseException;
import java.util.List;
/**
* @author 宋欢
*/
@Api(value = "UserController", tags = "用户")
@RestController
@RequestMapping(value = {"user"})
@Validated
public class UserController {
@Autowired
private UserService service;
@ApiOperation(value = "查询列表", produces = "application/json")
@RequestMapping(value = "/find-list", method = RequestMethod.GET)
public List<User> findList() {
return service.findList();
}
@ApiOperation(value = "查询总数", produces = "application/json")
@RequestMapping(value = "/total-num", method = RequestMethod.GET)
public long getTotalNum() {
return service.getTotalNum();
}
@ApiOperation(value = "通过主键,获取一条记录", produces = "application/json")
@RequestMapping(value = "/find", method = RequestMethod.GET)
public User find() {
return service.find();
}
@ApiOperation(value = "新增多条记录", produces = "application/json")
@RequestMapping(value = "/insert-list", method = RequestMethod.POST)
public long insertList() throws ParseException {
return service.insertList();
}
@ApiOperation(value = "新增一条记录", produces = "application/json")
@RequestMapping(value = "/insert", method = RequestMethod.POST)
public int insert() throws ParseException {
return service.insert();
}
@ApiOperation(value = "通过主键,修改多条记录", produces = "application/json")
@RequestMapping(value = "/update-list", method = RequestMethod.POST)
public long updateList() {
return service.updateList();
}
@ApiOperation(value = "通过主键,修改一条记录", produces = "application/json")
@RequestMapping(value = "/update", method = RequestMethod.POST)
public int update() {
return service.update();
}
}
package cn.qmai.study.java.demo.web.main;
import io.swagger.annotations.ApiOperation;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportResource;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @author 宋欢
*/
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableTransactionManagement
@EnableScheduling
@ComponentScan(basePackages = {"cn.qmai.study.java.demo"})
@ImportResource(locations = {"classpath:data-sharing.xml"})
@EnableSwagger2
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public Docket swaggerSpringMvcPlugin() {
return new Docket(DocumentationType.SWAGGER_2).
enable(true).
select().
apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)).
paths(PathSelectors.any()).
build().
apiInfo(new ApiInfoBuilder().
title("MyBatis Demo").
description("").
version("1.0").
build());
}
}
server:
port: 8080
servlet:
context-path: /
tomcat:
uri-encoding: UTF-8
max-connections: 20000
max-threads: 1000
min-spare-threads: 30
spring:
application:
name: mybatis-demo
messages:
basename: i18n/messages
aop:
proxy-target-class: true
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- DataSource公共属性配置,使用 Druid 连接池 -->
<bean id="abstractDataSource" abstract="true" class="com.alibaba.druid.pool.DruidDataSource" init-method="init"
destroy-method="close">
<!-- 初始化连接 -->
<property name="initialSize" value="10"/>
<!-- 最小空闲连接 -->
<property name="minIdle" value="10"/>
<!-- 最大连接数量 -->
<property name="maxActive" value="100"/>
<!-- 连接保持空闲而不被驱逐的最小时间,单位:毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000"/>
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="60000"/>
<!-- 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。-->
<property name="validationQuery" value="select 1"/>
<!-- 这里建议配置为TRUE,防止取到的连接不可用。获取链接的时候,不校验是否可用,开启会有损性能 -->
<property name="testOnBorrow" value="false"/>
<!-- 归还链接到连接池的时候校验链接是否可用 -->
<property name="testOnReturn" value="false"/>
<!-- 此项配置为true即可,不影响性能,并且保证安全性。意义为:申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效 -->
<property name="testWhileIdle" value="true"/>
<!-- 超过时间限制时间(单位秒),目前为5分钟,如果有业务处理时间超过5分钟,可以适当调整。-->
<property name="removeAbandonedTimeout" value="1800"/>
</bean>
<!-- 配置,连接、用户名、密码 -->
<bean id="dataSynDs" parent="abstractDataSource" primary="false">
<property name="url"
value="jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=Asia/Shanghai&amp;allowMultiQueries=true"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
</bean>
<!-- Mybatis 配置 -->
<bean id="dataSynMybatis" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSynDs"/>
<property name="typeAliasesPackage" value="cn.qmai.study.java.demo.biz.model"/>
<property name="mapperLocations" value="classpath:/mappings/*.xml"/>
<property name="configLocation" value="classpath:/mybatis.xml"/>
<property name="vfs" value="org.mybatis.spring.boot.autoconfigure.SpringBootVFS"/>
</bean>
<!-- Mybatis 接口扫描 -->
<bean id="dataSynScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="dataSynMybatis"/>
<property name="basePackage" value="cn.qmai.study.java.demo.biz.dao"/>
</bean>
<!-- 定义事务 -->
<bean id="dataSynTransaction" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSynDs"/>
</bean>
</beans>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="appName" value="mybatis-demo"/>
<!--引入springboot的默认日志配置-->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<pattern>
<pattern>
{
"biz": "${appName}",
"thread": "%thread",
"message": "%ex",
"context": "%m",
"level": "%level",
"time": "%date{ISO8601}"
}
</pattern>
</pattern>
</providers>
</encoder>
</appender>
<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>logs/file.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>logs/file.%i.log.gz</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>1</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>200MB</maxFileSize>
</triggeringPolicy>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<pattern>
<pattern>
{
"biz": "${appName}",
"thread": "%thread",
"message": "%ex",
"context": "%m",
"level": "%level",
"time": "%date{ISO8601}"
}
</pattern>
</pattern>
</providers>
</encoder>
</appender>
<appender name="LOG_MONITOR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>logs/monitorFile.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>logs/monitor.file.%i.log.gz</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>1</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>200MB</maxFileSize>
</triggeringPolicy>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<pattern>
<pattern>
{
"biz": "${appName}",
"thread": "%thread",
"message": "%ex",
"context": "%m",
"level": "%level",
"time": "%date{ISO8601}"
}
</pattern>
</pattern>
</providers>
</encoder>
</appender>
<!-- 异步输出 -->
<appender name="LOG_MONITOR_FILE_ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<!-- 默认为 false,在队列满的时候 appender 会阻塞而不是丢弃信息。设置为 true,appender 不会阻塞你的应用而会将消息丢弃 -->
<neverBlock>true</neverBlock>
<!-- 不丢失日志。默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>1638</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能。默认值为256 -->
<queueSize>2048</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="LOG_MONITOR_FILE"/>
</appender>
<!-- 异步输出 -->
<appender name="ROLLING_FILE_ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<!-- 默认为 false,在队列满的时候 appender 会阻塞而不是丢弃信息。设置为 true,appender 不会阻塞你的应用而会将消息丢弃 -->
<neverBlock>true</neverBlock>
<!-- 不丢失日志。默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>1638</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能。默认值为256 -->
<queueSize>2048</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="ROLLING_FILE"/>
</appender>
<!-- 控制台输出日志级别 -->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<!-- <appender-ref ref="ROLLING_FILE_ASYNC"/> -->
</root>
<logger name="log_monitor" level="INFO" additivity="false">
<appender-ref ref="LOG_MONITOR_FILE_ASYNC"/>
</logger>
</configuration>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 全局参数 -->
<settings>
<!-- 使全局的映射器启用或禁用缓存-->
<setting name="cacheEnabled" value="true"/>
<!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载 -->
<setting name="aggressiveLazyLoading" value="true"/>
<!-- 是否允许单条sql,返回多个数据集(取决于驱动的兼容性),default: true -->
<setting name="multipleResultSetsEnabled" value="true"/>
<!-- 是否可以使用列的别名(取决于驱动的兼容性),default: true -->
<setting name="useColumnLabel" value="true"/>
<!-- 允许 JDBC 生成主键。需要驱动器支持。如果设为了true,这个设置将强制使用被生成的主键,有一些驱动器不兼容不过仍然可以执行。default: false -->
<setting name="useGeneratedKeys" value="false"/>
<!-- 指定 MyBatis 如何自动映射 数据基表的列(NONE:不隐射、PARTIAL:部分、FULL:全部) -->
<setting name="autoMappingBehavior" value="PARTIAL"/>
<!-- 这是默认的执行类型(SIMPLE:简单、REUSE:执行器可能重复使用prepared statements语句、BATCH:执行器可以重复执行语句和批量更新)-->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!-- 使用驼峰命名法转换字段 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 设置本地缓存范围(session:有数据的共享、statement:语句范围,不会有数据的共享),default: session -->
<setting name="localCacheScope" value="STATEMENT"/>
<!-- 设置但JDBC类型为空时,某些驱动程序要指定值,default: OTHER,插入空值时不需要指定类型 -->
<setting name="jdbcTypeForNull" value="NULL"/>
<!-- 打印SQL日志 -->
<!-- <setting name="logImpl" value="STDOUT_LOGGING"/>-->
</settings>
<plugins>
<plugin interceptor="cn.qmai.study.java.demo.biz.interceptor.ExecutorInterceptor">
<property name="databaseType" value="mysql"/>
</plugin>
</plugins>
</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<groupId>cn.qmai.study.java.demo</groupId>
<artifactId>mybatis-demo</artifactId>
<version>1.0.1.SNAPSHOT</version>
<properties>
<encoding>UTF-8</encoding>
<java.version>1.8</java.version>
<maven.version>3.7.0</maven.version>
<maven-plugin.version>3.3.0</maven-plugin.version>
<spring-boot.version>2.1.6.RELEASE</spring-boot.version>
<fastjson.version>1.2.36</fastjson.version>
<alibaba-druid.version>1.1.20</alibaba-druid.version>
<mysql-connector.version>8.0.16</mysql-connector.version>
<mybatis.version>2.0.1</mybatis.version>
<swagger.version>2.9.2</swagger.version>
<slf4j.version>1.7.30</slf4j.version>
<logback.version>6.4</logback.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${alibaba-druid.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>${logback.version}</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<modules>
<module>demo-biz</module>
<module>demo-web</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${encoding}</encoding>
<showWarnings>true</showWarnings>
<optimize>true</optimize>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
CREATE TABLE user
(
id bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户id',
phone varchar(32) DEFAULT NULL COMMENT '手机号',
username varchar(255) DEFAULT NULL COMMENT '姓名',
gender int(11) unsigned DEFAULT NULL COMMENT '性别,0-未知、1-男性、2-女性、3-疑似男性、4-疑似女性',
birthday date DEFAULT NULL COMMENT '出生日,年-月-日,如:2006-01-02',
email varchar(255) DEFAULT NULL COMMENT '邮箱',
is_active int(11) unsigned DEFAULT NULL COMMENT '有效?1-有效、0-无效',
remark varchar(255) DEFAULT NULL COMMENT '备注',
is_deleted bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '删除?id-是、0-否',
created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
deleted_at datetime DEFAULT NULL COMMENT '删除时间',
PRIMARY KEY (id),
UNIQUE KEY uk_phone (phone, is_deleted),
KEY idx_username (username, is_deleted),
KEY idx_created_at (is_deleted, created_at)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT = '用户';
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment