From 55a9e7864e91e8fab5240c8c96d7b28dfc52191d Mon Sep 17 00:00:00 2001 From: "Yangkai.Shen" <237497819@qq.com> Date: Tue, 16 Oct 2018 16:49:45 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E9=9B=86=E6=88=90=20Jdbc=20Templa?= =?UTF-8?q?te=EF=BC=8C=E5=B9=B6=E7=AE=80=E6=98=93=E5=B0=81=E8=A3=85?= =?UTF-8?q?=E9=80=9A=E7=94=A8=20Dao=20=E5=B1=82=EF=BC=8C=E9=80=9A=E7=94=A8?= =?UTF-8?q?=E5=A2=9E=E5=88=A0=E6=94=B9=E6=9F=A5=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../annotation/{Auto.java => Pk.java} | 12 +- .../orm/jdbctemplate/constant/Const.java | 8 + .../controller/UserController.java | 30 ++- .../orm/jdbctemplate/dao/UserDao.java | 45 +++- .../orm/jdbctemplate/dao/base/BaseDao.java | 197 +++++++++++++++--- .../orm/jdbctemplate/entity/User.java | 4 +- .../jdbctemplate/service/IUserService.java | 36 ++++ .../service/impl/UserServiceImpl.java | 63 +++++- 8 files changed, 358 insertions(+), 37 deletions(-) rename spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/annotation/{Auto.java => Pk.java} (77%) diff --git a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/annotation/Auto.java b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/annotation/Pk.java similarity index 77% rename from spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/annotation/Auto.java rename to spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/annotation/Pk.java index 2f71566..aea8366 100644 --- a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/annotation/Auto.java +++ b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/annotation/Pk.java @@ -7,11 +7,11 @@ import java.lang.annotation.Target; /** *

- * 自增列注解 + * 主键注解 *

* * @package: com.xkcoding.orm.jdbctemplate.annotation - * @description: 自增列注解 + * @description: 主键注解 * @author: yangkai.shen * @date: Created in 2018/10/15 11:23 AM * @copyright: Copyright (c) 2018 @@ -20,5 +20,11 @@ import java.lang.annotation.Target; */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) -public @interface Auto { +public @interface Pk { + /** + * 自增 + * + * @return 自增主键 + */ + boolean auto() default true; } diff --git a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/constant/Const.java b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/constant/Const.java index 8d4881d..2156ea5 100644 --- a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/constant/Const.java +++ b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/constant/Const.java @@ -14,5 +14,13 @@ package com.xkcoding.orm.jdbctemplate.constant; * @modified: yangkai.shen */ public interface Const { + /** + * 加密盐前缀 + */ String SALT_PREFIX = "::SpringBootDemo::"; + + /** + * 逗号分隔符 + */ + String SEPARATOR_COMMA = ","; } diff --git a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/controller/UserController.java b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/controller/UserController.java index 72829bb..4616ff3 100644 --- a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/controller/UserController.java +++ b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/controller/UserController.java @@ -5,9 +5,9 @@ import com.xkcoding.orm.jdbctemplate.entity.User; import com.xkcoding.orm.jdbctemplate.service.IUserService; import lombok.extern.slf4j.Slf4j; 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.RestController; +import org.springframework.web.bind.annotation.*; + +import java.util.List; /** *

@@ -37,4 +37,28 @@ public class UserController { Boolean save = userService.save(user); return Dict.create().set("code", save ? 200 : 500).set("msg", save ? "成功" : "失败").set("data", save ? user : null); } + + @DeleteMapping("/user/{id}") + public Dict delete(@PathVariable Long id) { + Boolean delete = userService.delete(id); + return Dict.create().set("code", delete ? 200 : 500).set("msg", delete ? "成功" : "失败"); + } + + @PutMapping("/user/{id}") + public Dict update(@RequestBody User user, @PathVariable Long id) { + Boolean update = userService.update(user, id); + return Dict.create().set("code", update ? 200 : 500).set("msg", update ? "成功" : "失败").set("data", update ? user : null); + } + + @GetMapping("/user/{id}") + public Dict getUser(@PathVariable Long id) { + User user = userService.getUser(id); + return Dict.create().set("code", 200).set("msg", "成功").set("data", user); + } + + @GetMapping("/user") + public Dict getUser(User user) { + List userList = userService.getUser(user); + return Dict.create().set("code", 200).set("msg", "成功").set("data", userList); + } } diff --git a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/dao/UserDao.java b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/dao/UserDao.java index a114008..0ccf990 100644 --- a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/dao/UserDao.java +++ b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/dao/UserDao.java @@ -6,6 +6,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; +import java.util.List; + /** *

* User Dao @@ -20,7 +22,7 @@ import org.springframework.stereotype.Repository; * @modified: yangkai.shen */ @Repository -public class UserDao extends BaseDao { +public class UserDao extends BaseDao { @Autowired public UserDao(JdbcTemplate jdbcTemplate) { @@ -36,4 +38,45 @@ public class UserDao extends BaseDao { public Integer insert(User user) { return super.insert(user, true); } + + /** + * 根据主键删除用户 + * + * @param id 主键id + * @return 操作影响行数 + */ + public Integer delete(Long id) { + return super.deleteById(id); + } + + /** + * 更新用户 + * + * @param user 用户对象 + * @param id 主键id + * @return 操作影响行数 + */ + public Integer update(User user, Long id) { + return super.updateById(user, id, true); + } + + /** + * 根据主键获取用户 + * + * @param id 主键id + * @return id对应的用户 + */ + public User selectById(Long id) { + return super.findOneById(id); + } + + /** + * 根据查询条件获取用户列表 + * + * @param user 用户查询条件 + * @return 用户列表 + */ + public List selectUserList(User user) { + return super.findByExample(user); + } } diff --git a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/dao/base/BaseDao.java b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/dao/base/BaseDao.java index 4c7958e..42c735d 100644 --- a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/dao/base/BaseDao.java +++ b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/dao/base/BaseDao.java @@ -1,20 +1,27 @@ package com.xkcoding.orm.jdbctemplate.dao.base; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; -import com.xkcoding.orm.jdbctemplate.annotation.Auto; import com.xkcoding.orm.jdbctemplate.annotation.Column; import com.xkcoding.orm.jdbctemplate.annotation.Ignore; +import com.xkcoding.orm.jdbctemplate.annotation.Pk; import com.xkcoding.orm.jdbctemplate.annotation.Table; +import com.xkcoding.orm.jdbctemplate.constant.Const; import lombok.extern.slf4j.Slf4j; +import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -32,46 +39,168 @@ import java.util.stream.Stream; * @modified: yangkai.shen */ @Slf4j -public class BaseDao { +public class BaseDao { private JdbcTemplate jdbcTemplate; + private Class clazz; + @SuppressWarnings(value = "unchecked") public BaseDao(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; + clazz = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; } /** - * 通用插入 + * 通用插入,自增列需要添加 {@link Pk} 注解 * * @param t 对象 * @param ignoreNull 是否忽略 null 值 * @return 操作的行数 */ protected Integer insert(T t, Boolean ignoreNull) { + String table = getTableName(t); + + List filterField = getField(t, ignoreNull); + + List columnList = getColumns(filterField); + + String columns = StrUtil.join(Const.SEPARATOR_COMMA, columnList); + + // 构造占位符 + String params = StrUtil.repeatAndJoin("?", columnList.size(), Const.SEPARATOR_COMMA); + + // 构造值 + Object[] values = filterField.stream().map(field -> ReflectUtil.getFieldValue(t, field)).toArray(); + + String sql = StrUtil.format("INSERT INTO {table} ({columns}) VALUES ({params})", Dict.create().set("table", table).set("columns", columns).set("params", params)); + log.debug("【执行SQL】SQL:{}", sql); + log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(values)); + return jdbcTemplate.update(sql, values); + } + + /** + * 通用根据主键删除 + * + * @param pk 主键 + * @return 影响行数 + */ + protected Integer deleteById(P pk) { + String tableName = getTableName(); + String sql = StrUtil.format("DELETE FROM {table} where id = ?", Dict.create().set("table", tableName)); + log.debug("【执行SQL】SQL:{}", sql); + log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(pk)); + return jdbcTemplate.update(sql, pk); + } + + /** + * 通用根据主键更新,自增列需要添加 {@link Pk} 注解 + * + * @param t 对象 + * @param pk 主键 + * @param ignoreNull 是否忽略 null 值 + * @return 操作的行数 + */ + protected Integer updateById(T t, P pk, Boolean ignoreNull) { + String tableName = getTableName(t); + + List filterField = getField(t, ignoreNull); + + List columnList = getColumns(filterField); + + List columns = columnList.stream().map(s -> StrUtil.appendIfMissing(s, " = ?")).collect(Collectors.toList()); + String params = StrUtil.join(Const.SEPARATOR_COMMA, columns); + + // 构造值 + List valueList = filterField.stream().map(field -> ReflectUtil.getFieldValue(t, field)).collect(Collectors.toList()); + valueList.add(pk); + + Object[] values = ArrayUtil.toArray(valueList, Object.class); + + String sql = StrUtil.format("UPDATE {table} SET {params} where id = ?", Dict.create().set("table", tableName).set("params", params)); + log.debug("【执行SQL】SQL:{}", sql); + log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(values)); + return jdbcTemplate.update(sql, values); + } + + /** + * 通用根据主键查询单条记录 + * + * @param pk 主键 + * @return 单条记录 + */ + public T findOneById(P pk) { + String tableName = getTableName(); + String sql = StrUtil.format("SELECT * FROM {table} where id = ?", Dict.create().set("table", tableName)); + RowMapper rowMapper = new BeanPropertyRowMapper<>(clazz); + log.debug("【执行SQL】SQL:{}", sql); + log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(pk)); + return jdbcTemplate.queryForObject(sql, new Object[]{pk}, rowMapper); + } + + /** + * 根据对象查询 + * + * @param t 查询条件 + * @return 对象列表 + */ + public List findByExample(T t) { + String tableName = getTableName(t); + List filterField = getField(t, true); + List columnList = getColumns(filterField); + + List columns = columnList.stream().map(s -> " and " + s + " = ? ").collect(Collectors.toList()); + + String where = StrUtil.join(" ", columns); + // 构造值 + Object[] values = filterField.stream().map(field -> ReflectUtil.getFieldValue(t, field)).toArray(); + + String sql = StrUtil.format("SELECT * FROM {table} where 1=1 {where}", Dict.create().set("table", tableName).set("where", StrUtil.isBlank(where) ? "" : where)); + log.debug("【执行SQL】SQL:{}", sql); + log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(values)); + List> maps = jdbcTemplate.queryForList(sql, values); + List ret = CollUtil.newArrayList(); + maps.forEach(map -> ret.add(BeanUtil.fillBeanWithMap(map, ReflectUtil.newInstance(clazz), true, false))); + return ret; + } + + /** + * 获取表名 + * + * @param t 对象 + * @return 表名 + */ + private String getTableName(T t) { Table tableAnnotation = t.getClass().getAnnotation(Table.class); - String table; if (ObjectUtil.isNotNull(tableAnnotation)) { - table = StrUtil.format("`{}`", tableAnnotation.name()); + return StrUtil.format("`{}`", tableAnnotation.name()); } else { - table = StrUtil.format("`{}`", t.getClass().getName().toLowerCase()); + return StrUtil.format("`{}`", t.getClass().getName().toLowerCase()); } + } - // 获取所有字段,包含父类中的字段 - Field[] fields = ReflectUtil.getFields(t.getClass()); - - // 过滤数据库中不存在的字段,以及自增列 - List filterField; - Stream fieldStream = CollUtil.toList(fields).stream().filter(field -> ObjectUtil.isNull(field.getAnnotation(Ignore.class)) || ObjectUtil.isNull(field.getAnnotation(Auto.class))); - - // 是否过滤字段值为null的字段 - if (ignoreNull) { - filterField = fieldStream.filter(field -> ObjectUtil.isNotNull(ReflectUtil.getFieldValue(t, field))).collect(Collectors.toList()); + /** + * 获取表名 + * + * @return 表名 + */ + private String getTableName() { + Table tableAnnotation = clazz.getAnnotation(Table.class); + if (ObjectUtil.isNotNull(tableAnnotation)) { + return StrUtil.format("`{}`", tableAnnotation.name()); } else { - filterField = fieldStream.collect(Collectors.toList()); + return StrUtil.format("`{}`", clazz.getName().toLowerCase()); } + } + /** + * 获取列 + * + * @param fieldList 字段列表 + * @return 列信息列表 + */ + private List getColumns(List fieldList) { // 构造列 List columnList = CollUtil.newArrayList(); - for (Field field : filterField) { + for (Field field : fieldList) { Column columnAnnotation = field.getAnnotation(Column.class); String columnName; if (ObjectUtil.isNotNull(columnAnnotation)) { @@ -81,17 +210,31 @@ public class BaseDao { } columnList.add(StrUtil.format("`{}`", columnName)); } - String columns = StrUtil.join(",", columnList); + return columnList; + } - // 构造占位符 - String params = StrUtil.repeatAndJoin("?", columnList.size(), ","); + /** + * 获取字段列表 {@code 过滤数据库中不存在的字段,以及自增列} + * + * @param t 对象 + * @param ignoreNull 是否忽略空值 + * @return 字段列表 + */ + private List getField(T t, Boolean ignoreNull) { + // 获取所有字段,包含父类中的字段 + Field[] fields = ReflectUtil.getFields(t.getClass()); - // 构造值 - Object[] values = filterField.stream().map(field -> ReflectUtil.getFieldValue(t, field)).toArray(); + // 过滤数据库中不存在的字段,以及自增列 + List filterField; + Stream fieldStream = CollUtil.toList(fields).stream().filter(field -> ObjectUtil.isNull(field.getAnnotation(Ignore.class)) || ObjectUtil.isNull(field.getAnnotation(Pk.class))); - String sql = StrUtil.format("INSERT INTO {table} ({columns}) VALUES ({params})", Dict.create().set("table", table).set("columns", columns).set("params", params)); - log.debug("【执行SQL】SQL:{}", sql); - log.debug("【执行SQL】参数:{}", JSONUtil.toJsonStr(values)); - return jdbcTemplate.update(sql, values); + // 是否过滤字段值为null的字段 + if (ignoreNull) { + filterField = fieldStream.filter(field -> ObjectUtil.isNotNull(ReflectUtil.getFieldValue(t, field))).collect(Collectors.toList()); + } else { + filterField = fieldStream.collect(Collectors.toList()); + } + return filterField; } + } diff --git a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/entity/User.java b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/entity/User.java index 1dfe56b..e21697b 100644 --- a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/entity/User.java +++ b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/entity/User.java @@ -1,6 +1,6 @@ package com.xkcoding.orm.jdbctemplate.entity; -import com.xkcoding.orm.jdbctemplate.annotation.Auto; +import com.xkcoding.orm.jdbctemplate.annotation.Pk; import com.xkcoding.orm.jdbctemplate.annotation.Column; import com.xkcoding.orm.jdbctemplate.annotation.Table; import lombok.Data; @@ -27,7 +27,7 @@ public class User implements Serializable { /** * 主键 */ - @Auto + @Pk private Long id; /** diff --git a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/service/IUserService.java b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/service/IUserService.java index 332e4cf..c4b686e 100644 --- a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/service/IUserService.java +++ b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/service/IUserService.java @@ -2,6 +2,8 @@ package com.xkcoding.orm.jdbctemplate.service; import com.xkcoding.orm.jdbctemplate.entity.User; +import java.util.List; + /** *

* User Service @@ -23,4 +25,38 @@ public interface IUserService { * @return 保存成功 {@code true} 保存失败 {@code false} */ Boolean save(User user); + + /** + * 删除用户 + * + * @param id 主键id + * @return 删除成功 {@code true} 删除失败 {@code false} + */ + Boolean delete(Long id); + + /** + * 更新用户 + * + * @param user 用户实体 + * @param id 主键id + * @return 更新成功 {@code true} 更新失败 {@code false} + */ + Boolean update(User user, Long id); + + /** + * 获取单个用户 + * + * @param id 主键id + * @return 单个用户对象 + */ + User getUser(Long id); + + /** + * 获取用户列表 + * + * @param user 用户实体 + * @return 用户列表 + */ + List getUser(User user); + } diff --git a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/service/impl/UserServiceImpl.java b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/service/impl/UserServiceImpl.java index 3163870..6f0dccf 100644 --- a/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/service/impl/UserServiceImpl.java +++ b/spring-boot-demo-orm-jdbctemplate/src/main/java/com/xkcoding/orm/jdbctemplate/service/impl/UserServiceImpl.java @@ -1,6 +1,10 @@ package com.xkcoding.orm.jdbctemplate.service.impl; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.bean.copier.CopyOptions; +import cn.hutool.core.date.DateTime; import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; import com.xkcoding.orm.jdbctemplate.constant.Const; import com.xkcoding.orm.jdbctemplate.dao.UserDao; @@ -9,6 +13,8 @@ import com.xkcoding.orm.jdbctemplate.service.IUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.List; + /** *

* User Service Implement @@ -41,9 +47,64 @@ public class UserServiceImpl implements IUserService { public Boolean save(User user) { String rawPass = user.getPassword(); String salt = IdUtil.simpleUUID(); - String pass = SecureUtil.md5(rawPass+ Const.SALT_PREFIX+salt); + String pass = SecureUtil.md5(rawPass + Const.SALT_PREFIX + salt); user.setPassword(pass); user.setSalt(salt); return userDao.insert(user) > 0; } + + /** + * 删除用户 + * + * @param id 主键id + * @return 删除成功 {@code true} 删除失败 {@code false} + */ + @Override + public Boolean delete(Long id) { + return userDao.delete(id) > 0; + } + + /** + * 更新用户 + * + * @param user 用户实体 + * @param id 主键id + * @return 更新成功 {@code true} 更新失败 {@code false} + */ + @Override + public Boolean update(User user, Long id) { + User exist = getUser(id); + if (StrUtil.isNotBlank(user.getPassword())) { + String rawPass = user.getPassword(); + String salt = IdUtil.simpleUUID(); + String pass = SecureUtil.md5(rawPass + Const.SALT_PREFIX + salt); + user.setPassword(pass); + user.setSalt(salt); + } + BeanUtil.copyProperties(user, exist, CopyOptions.create().setIgnoreNullValue(true)); + exist.setLastUpdateTime(new DateTime()); + return userDao.update(exist, id) > 0; + } + + /** + * 获取单个用户 + * + * @param id 主键id + * @return 单个用户对象 + */ + @Override + public User getUser(Long id) { + return userDao.findOneById(id); + } + + /** + * 获取用户列表 + * + * @param user 用户实体 + * @return 用户列表 + */ + @Override + public List getUser(User user) { + return userDao.findByExample(user); + } }