|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- # spring-boot-demo-orm-jdbctemplate
- > 本 demo 主要演示了Spring Boot如何使用 JdbcTemplate 操作数据库,并且简易地封装了一个通用的 Dao 层,包括增删改查。
-
- ## pom.xml
-
- ```xml
- <?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>spring-boot-demo-orm-jdbctemplate</artifactId>
- <version>1.0.0-SNAPSHOT</version>
- <packaging>jar</packaging>
-
- <name>spring-boot-demo-orm-jdbctemplate</name>
- <description>Demo project for Spring Boot</description>
-
- <parent>
- <groupId>com.xkcoding</groupId>
- <artifactId>spring-boot-demo</artifactId>
- <version>1.0.0-SNAPSHOT</version>
- </parent>
-
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <java.version>1.8</java.version>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-jdbc</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- </dependency>
-
- <dependency>
- <groupId>cn.hutool</groupId>
- <artifactId>hutool-all</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <optional>true</optional>
- </dependency>
- </dependencies>
-
- <build>
- <finalName>spring-boot-demo-orm-jdbctemplate</finalName>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
-
- </project>
- ```
-
- ## BaseDao.java
-
- ```java
- /**
- * <p>
- * Dao基类
- * </p>
- *
- * @author yangkai.shen
- * @date Created in 2018-10-15 11:28
- */
- @Slf4j
- public class BaseDao<T, P> {
- private JdbcTemplate jdbcTemplate;
- private Class<T> clazz;
-
- @SuppressWarnings(value = "unchecked")
- public BaseDao(JdbcTemplate jdbcTemplate) {
- this.jdbcTemplate = jdbcTemplate;
- clazz = (Class<T>) ((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<Field> filterField = getField(t, ignoreNull);
-
- List<String> 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<Field> filterField = getField(t, ignoreNull);
-
- List<String> columnList = getColumns(filterField);
-
- List<String> columns = columnList.stream().map(s -> StrUtil.appendIfMissing(s, " = ?")).collect(Collectors.toList());
- String params = StrUtil.join(Const.SEPARATOR_COMMA, columns);
-
- // 构造值
- List<Object> 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<T> 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<T> findByExample(T t) {
- String tableName = getTableName(t);
- List<Field> filterField = getField(t, true);
- List<String> columnList = getColumns(filterField);
-
- List<String> 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<Map<String, Object>> maps = jdbcTemplate.queryForList(sql, values);
- List<T> 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);
- if (ObjectUtil.isNotNull(tableAnnotation)) {
- return StrUtil.format("`{}`", tableAnnotation.name());
- } else {
- return StrUtil.format("`{}`", t.getClass().getName().toLowerCase());
- }
- }
-
- /**
- * 获取表名
- *
- * @return 表名
- */
- private String getTableName() {
- Table tableAnnotation = clazz.getAnnotation(Table.class);
- if (ObjectUtil.isNotNull(tableAnnotation)) {
- return StrUtil.format("`{}`", tableAnnotation.name());
- } else {
- return StrUtil.format("`{}`", clazz.getName().toLowerCase());
- }
- }
-
- /**
- * 获取列
- *
- * @param fieldList 字段列表
- * @return 列信息列表
- */
- private List<String> getColumns(List<Field> fieldList) {
- // 构造列
- List<String> columnList = CollUtil.newArrayList();
- for (Field field : fieldList) {
- Column columnAnnotation = field.getAnnotation(Column.class);
- String columnName;
- if (ObjectUtil.isNotNull(columnAnnotation)) {
- columnName = columnAnnotation.name();
- } else {
- columnName = field.getName();
- }
- columnList.add(StrUtil.format("`{}`", columnName));
- }
- return columnList;
- }
-
- /**
- * 获取字段列表 {@code 过滤数据库中不存在的字段,以及自增列}
- *
- * @param t 对象
- * @param ignoreNull 是否忽略空值
- * @return 字段列表
- */
- private List<Field> getField(T t, Boolean ignoreNull) {
- // 获取所有字段,包含父类中的字段
- Field[] fields = ReflectUtil.getFields(t.getClass());
-
- // 过滤数据库中不存在的字段,以及自增列
- List<Field> filterField;
- Stream<Field> fieldStream = CollUtil.toList(fields).stream().filter(field -> ObjectUtil.isNull(field.getAnnotation(Ignore.class)) || ObjectUtil.isNull(field.getAnnotation(Pk.class)));
-
- // 是否过滤字段值为null的字段
- if (ignoreNull) {
- filterField = fieldStream.filter(field -> ObjectUtil.isNotNull(ReflectUtil.getFieldValue(t, field))).collect(Collectors.toList());
- } else {
- filterField = fieldStream.collect(Collectors.toList());
- }
- return filterField;
- }
-
- }
- ```
-
- ## application.yml
-
- ```yaml
- server:
- port: 8080
- servlet:
- context-path: /demo
- spring:
- datasource:
- url: jdbc:mysql://127.0.0.1:3306/spring-boot-demo?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
- username: root
- password: root
- driver-class-name: com.mysql.cj.jdbc.Driver
- type: com.zaxxer.hikari.HikariDataSource
- initialization-mode: always
- continue-on-error: true
- schema:
- - "classpath:db/schema.sql"
- data:
- - "classpath:db/data.sql"
- hikari:
- minimum-idle: 5
- connection-test-query: SELECT 1 FROM DUAL
- maximum-pool-size: 20
- auto-commit: true
- idle-timeout: 30000
- pool-name: SpringBootDemoHikariCP
- max-lifetime: 60000
- connection-timeout: 30000
- logging:
- level:
- com.xkcoding: debug
- ```
-
- ## 备注
-
- 其余详细代码参见 demo
|