From 5d77ca584bc7ff169653c20984636ca4cb0528d8 Mon Sep 17 00:00:00 2001 From: vonchange Date: Mon, 15 Apr 2024 14:48:00 +0800 Subject: [PATCH 01/15] =?UTF-8?q?[new]=20bug=E4=BF=AE=E5=A4=8D=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E5=91=BD=E5=90=8D=E5=92=8Cmd=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spring-data-jdbc-mybatis/pom.xml | 2 +- .../jdbc/mybatis/core/support/JdbcRepositoryQuery.java | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/spring-data-jdbc-mybatis/pom.xml b/spring-data-jdbc-mybatis/pom.xml index 72efa29..21f946f 100644 --- a/spring-data-jdbc-mybatis/pom.xml +++ b/spring-data-jdbc-mybatis/pom.xml @@ -8,7 +8,7 @@ 2.5.0 spring-data-jdbc-mybatis - 2.5.0.1 + 2.5.0.2 spring-data-jdbc-mybatis spring data jdbc with mybatis template dynamic query diff --git a/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcRepositoryQuery.java b/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcRepositoryQuery.java index 958c002..79e57b8 100644 --- a/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcRepositoryQuery.java +++ b/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcRepositoryQuery.java @@ -16,6 +16,7 @@ package com.vonchange.jdbc.mybatis.core.support; import com.vonchange.common.util.ClazzUtils; +import com.vonchange.common.util.MarkdownUtil; import com.vonchange.common.util.StringPool; import com.vonchange.jdbc.config.ConstantJdbc; import com.vonchange.jdbc.core.CrudClient; @@ -89,8 +90,11 @@ class JdbcRepositoryQuery implements RepositoryQuery { boolean nameQuery=true; SqlParam sqlParam = null; if(null!=configInfo.getLocation()){ - nameQuery =false; - sqlId = configInfo.getLocation() + StringPool.DOT + configInfo.getMethod(); + String sqlIdInMd = configInfo.getLocation() + StringPool.DOT + configInfo.getMethod(); + if(null!=MarkdownUtil.getContent(sqlIdInMd,false)){ + sqlId=sqlIdInMd; + nameQuery =false; + } } if(nameQuery){ Assert.notNull(configInfo.getDomainType(),"domain type must not null,define crudRepository"); -- Gitee From 91b304e021f72173bcc5adffd0382ec54a03e0a3 Mon Sep 17 00:00:00 2001 From: vonchange Date: Tue, 7 May 2024 14:34:04 +0800 Subject: [PATCH 02/15] =?UTF-8?q?[bug]=20findAll=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spring-data-jdbc-mybatis/pom.xml | 2 +- .../jdbc/mybatis/core/support/SimpleJdbcRepository.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-data-jdbc-mybatis/pom.xml b/spring-data-jdbc-mybatis/pom.xml index 21f946f..92bf06f 100644 --- a/spring-data-jdbc-mybatis/pom.xml +++ b/spring-data-jdbc-mybatis/pom.xml @@ -8,7 +8,7 @@ 2.5.0 spring-data-jdbc-mybatis - 2.5.0.2 + 2.5.0.3 spring-data-jdbc-mybatis spring data jdbc with mybatis template dynamic query diff --git a/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/SimpleJdbcRepository.java b/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/SimpleJdbcRepository.java index 74bb2ec..26a983a 100644 --- a/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/SimpleJdbcRepository.java +++ b/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/SimpleJdbcRepository.java @@ -110,13 +110,13 @@ public class SimpleJdbcRepository implements CrudExtendRepository @SuppressWarnings("unchecked") public Iterable findAll() { Class tClass= (Class) configInfo.getDomainType(); - return crudClient.sqlId(NameQueryUtil.simpleNameSql("findAll",configInfo.getDomainType())) + return crudClient.jdbc().sql(NameQueryUtil.simpleNameSql("findAll",configInfo.getDomainType())) .query(tClass).iterable(); } @Override public long count() { - return crudClient.sqlId(NameQueryUtil.simpleNameSql("countAll",configInfo.getDomainType())).query(Long.class).single(); + return crudClient.jdbc().sql(NameQueryUtil.simpleNameSql("countAll",configInfo.getDomainType())).query(Long.class).single(); } @Override -- Gitee From 175d285e50f67ba4dadc21e99981e4b3fd590a87 Mon Sep 17 00:00:00 2001 From: vonchange Date: Tue, 25 Jun 2024 16:59:10 +0800 Subject: [PATCH 03/15] =?UTF-8?q?[bug]=20=E6=96=B0=E5=A2=9Emybatis=20jdbcT?= =?UTF-8?q?emplate=20=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jdbc-mybatis/pom.xml | 2 +- .../jdbc/{core => client}/CrudClient.java | 4 +- .../jdbc/core/DefaultCrudClient.java | 3 +- .../jdbc/mybatis/MybatisJdbcTemplate.java | 127 ++++++++++++++++++ .../com/vonchange/jdbc/util/JdbcUtil.java | 71 ++++++++++ 5 files changed, 203 insertions(+), 4 deletions(-) rename jdbc-mybatis/src/main/java/com/vonchange/jdbc/{core => client}/CrudClient.java (96%) create mode 100644 jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/MybatisJdbcTemplate.java create mode 100644 jdbc-mybatis/src/main/java/com/vonchange/jdbc/util/JdbcUtil.java diff --git a/jdbc-mybatis/pom.xml b/jdbc-mybatis/pom.xml index d40bbfa..05aec99 100644 --- a/jdbc-mybatis/pom.xml +++ b/jdbc-mybatis/pom.xml @@ -9,7 +9,7 @@ 4.0.0 jdbc-mybatis - 2.5.0.1 + 2.5.1 com.vonchange.common diff --git a/jdbc-mybatis/src/main/java/com/vonchange/jdbc/core/CrudClient.java b/jdbc-mybatis/src/main/java/com/vonchange/jdbc/client/CrudClient.java similarity index 96% rename from jdbc-mybatis/src/main/java/com/vonchange/jdbc/core/CrudClient.java rename to jdbc-mybatis/src/main/java/com/vonchange/jdbc/client/CrudClient.java index 116a085..212129e 100644 --- a/jdbc-mybatis/src/main/java/com/vonchange/jdbc/core/CrudClient.java +++ b/jdbc-mybatis/src/main/java/com/vonchange/jdbc/client/CrudClient.java @@ -1,4 +1,4 @@ -package com.vonchange.jdbc.core;/* +package com.vonchange.jdbc.client;/* * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,8 +15,8 @@ package com.vonchange.jdbc.core;/* */ -import com.vonchange.jdbc.client.JdbcClient; import com.vonchange.jdbc.config.ConstantJdbc; +import com.vonchange.jdbc.core.DefaultCrudClient; import com.vonchange.jdbc.mapper.AbstractPageWork; import com.vonchange.jdbc.model.DataSourceWrapper; import com.vonchange.mybatis.dialect.MySQLDialect; diff --git a/jdbc-mybatis/src/main/java/com/vonchange/jdbc/core/DefaultCrudClient.java b/jdbc-mybatis/src/main/java/com/vonchange/jdbc/core/DefaultCrudClient.java index 23c42c9..59edb09 100644 --- a/jdbc-mybatis/src/main/java/com/vonchange/jdbc/core/DefaultCrudClient.java +++ b/jdbc-mybatis/src/main/java/com/vonchange/jdbc/core/DefaultCrudClient.java @@ -2,6 +2,7 @@ package com.vonchange.jdbc.core; import com.vonchange.common.util.ConvertUtil; import com.vonchange.common.util.StringPool; +import com.vonchange.jdbc.client.CrudClient; import com.vonchange.jdbc.client.JdbcClient; import com.vonchange.jdbc.config.ConstantJdbc; import com.vonchange.jdbc.config.EnumRWType; @@ -29,7 +30,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -public class DefaultCrudClient implements CrudClient{ +public class DefaultCrudClient implements CrudClient { private static final Logger log = LoggerFactory.getLogger(DefaultCrudClient.class); private final MyJdbcTemplate classicOps; private final DataSourceWrapper dataSourceWrapper; diff --git a/jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/MybatisJdbcTemplate.java b/jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/MybatisJdbcTemplate.java new file mode 100644 index 0000000..fa28473 --- /dev/null +++ b/jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/MybatisJdbcTemplate.java @@ -0,0 +1,127 @@ +package com.vonchange.jdbc.mybatis; + +import com.vonchange.common.util.StringPool; +import com.vonchange.jdbc.model.SqlParam; +import com.vonchange.jdbc.util.JdbcUtil; +import com.vonchange.jdbc.util.MybatisTpl; +import com.vonchange.mybatis.dialect.Dialect; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.PreparedStatementCreator; +import org.springframework.jdbc.core.PreparedStatementCreatorFactory; +import org.springframework.jdbc.core.SqlParameter; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterUtils; +import org.springframework.jdbc.core.namedparam.ParsedSql; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.jdbc.support.JdbcUtils; +import org.springframework.lang.Nullable; + +import javax.sql.DataSource; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.Consumer; + +public abstract class MybatisJdbcTemplate extends NamedParameterJdbcTemplate { + public MybatisJdbcTemplate(DataSource dataSource) { + super(dataSource); + DatabaseMetaData metaData = null; + try { + metaData = dataSource.getConnection().getMetaData(); + String name = metaData.getDatabaseProductName().toLowerCase(Locale.ENGLISH); + //h2 + System.out.println("XXXX::"+name); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + public MybatisJdbcTemplate(JdbcOperations classicJdbcTemplate) { + super(classicJdbcTemplate); + } + + protected PreparedStatementCreator getPreparedStatementCreator(String sql, SqlParameterSource paramSource, + @Nullable Consumer customizer) { + Map param =toMap(paramSource); + SqlParam sqlParam = genSqlParam(sql,param); + if(null==sqlParam){ + return getPreparedStatementCreatorOriginal(sql,paramSource,customizer); + } + List declaredParameters = buildSqlParameterList(sqlParam.getParams()); + PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlParam.getSql(),declaredParameters); + if (customizer != null) { + customizer.accept(pscf); + } + Object[] paramObj=sqlParam.getParams().toArray(); + return pscf.newPreparedStatementCreator(paramObj); + } + protected PreparedStatementCreator getPreparedStatementCreatorOriginal(String sql, SqlParameterSource paramSource, + @Nullable Consumer customizer) { + + ParsedSql parsedSql = getParsedSql(sql); + PreparedStatementCreatorFactory pscf = getPreparedStatementCreatorFactory(parsedSql, paramSource); + if (customizer != null) { + customizer.accept(pscf); + } + Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null); + return pscf.newPreparedStatementCreator(params); + } + protected abstract Dialect dialect(); + private SqlParam genSqlParam(String sql,Map param){ + if(!sql.contains(StringPool.SPACE)){ + return MybatisTpl.generate("sql."+sql,param,dialect()); + } + if(sql.contains("[@")){//#{ spel 也有的 ||sql.contains("#{" + return MybatisTpl.generate(sql,sql,param,dialect()); + } + if(sql.contains("#{")){ + if(!sql.contains(":#{")){ + return MybatisTpl.generate(sql,sql,param,dialect()); + } + } + return null; + } + public static List buildSqlParameterList(Collection param) { + List params = new ArrayList<>(param.size()); + for (Object value : param) { + if(null==value){ + params.add(new SqlParameter(JdbcUtils.TYPE_UNKNOWN)); + continue; + } + params.add(new SqlParameter(JdbcUtil.sqlTypeFor(value.getClass()))); + } + return params; + } + public static List buildSqlParameterListX(SqlParameterSource paramSource) { + String[] paramNames = paramSource.getParameterNames(); + if (paramNames == null) { + return new ArrayList<>(); + } + List params = new ArrayList<>(paramNames.length); + for (String paramName : paramNames) { + params.add(new SqlParameter( + paramName, paramSource.getSqlType(paramName), paramSource.getTypeName(paramName))); + } + return params; + } + + private Map toMap( SqlParameterSource paramSource){ + String[] parameterNames = paramSource.getParameterNames(); + Map map = new HashMap<>(); + if(null==parameterNames){ + return map; + } + for (String paramName : parameterNames) { + map.put(paramName,paramSource.getValue(paramName)); + } + return map; + } + + + +} diff --git a/jdbc-mybatis/src/main/java/com/vonchange/jdbc/util/JdbcUtil.java b/jdbc-mybatis/src/main/java/com/vonchange/jdbc/util/JdbcUtil.java new file mode 100644 index 0000000..b600024 --- /dev/null +++ b/jdbc-mybatis/src/main/java/com/vonchange/jdbc/util/JdbcUtil.java @@ -0,0 +1,71 @@ +/* + * Copyright 2017-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.vonchange.jdbc.util; + + +import org.springframework.jdbc.support.JdbcUtils; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.HashMap; +import java.util.Map; + +/** + * Contains methods dealing with the quirks of JDBC, independent of any Entity, Aggregate or Repository abstraction. + * + * @author Jens Schauder + */ +public class JdbcUtil { + + private static final Map, Integer> sqlTypeMappings = new HashMap<>(); + + static { + + sqlTypeMappings.put(String.class, Types.VARCHAR); + sqlTypeMappings.put(BigInteger.class, Types.BIGINT); + sqlTypeMappings.put(BigDecimal.class, Types.NUMERIC); + sqlTypeMappings.put(Byte.class, Types.TINYINT); + sqlTypeMappings.put(byte.class, Types.TINYINT); + sqlTypeMappings.put(Short.class, Types.SMALLINT); + sqlTypeMappings.put(short.class, Types.SMALLINT); + sqlTypeMappings.put(Integer.class, Types.INTEGER); + sqlTypeMappings.put(int.class, Types.INTEGER); + sqlTypeMappings.put(Long.class, Types.BIGINT); + sqlTypeMappings.put(long.class, Types.BIGINT); + sqlTypeMappings.put(Double.class, Types.DOUBLE); + sqlTypeMappings.put(double.class, Types.DOUBLE); + sqlTypeMappings.put(Float.class, Types.REAL); + sqlTypeMappings.put(float.class, Types.REAL); + sqlTypeMappings.put(Boolean.class, Types.BIT); + sqlTypeMappings.put(boolean.class, Types.BIT); + sqlTypeMappings.put(byte[].class, Types.VARBINARY); + sqlTypeMappings.put(Date.class, Types.DATE); + sqlTypeMappings.put(Time.class, Types.TIME); + sqlTypeMappings.put(Timestamp.class, Types.TIMESTAMP); + } + + public static int sqlTypeFor(Class type) { + return sqlTypeMappings.keySet().stream() // + .filter(k -> k.isAssignableFrom(type)) // + .findFirst() // + .map(sqlTypeMappings::get) // + .orElse(JdbcUtils.TYPE_UNKNOWN); + } +} -- Gitee From d3d41deb0cfc2675efbcecaac7c0042cf26ed06f Mon Sep 17 00:00:00 2001 From: vonchange Date: Tue, 25 Jun 2024 16:59:56 +0800 Subject: [PATCH 04/15] =?UTF-8?q?[bug]=20=E6=96=B0=E5=A2=9EmybatisJdbcTemp?= =?UTF-8?q?late=E6=94=AF=E6=8C=81=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spring-data-jdbc-demo/.gitignore | 38 + spring-data-jdbc-demo/pom.xml | 138 ++++ .../main/java/com/vonchange/common/App.java | 37 + .../vonchange/common/dao/UserRepository.java | 32 + .../com/vonchange/common/domain/ReqUser.java | 16 + .../com/vonchange/common/domain/UserDTO.java | 14 + .../vonchange/common/domain/UserInfoDO.java | 33 + .../jdbc/core/convert/BasicJdbcConverter.java | 649 ++++++++++++++++++ .../src/main/resources/application-h2.yml | 19 + .../src/main/resources/application-mysql.yml | 19 + .../src/main/resources/application.properties | 3 + .../src/main/resources/application.yml | 18 + .../src/main/resources/db-init.sql | 21 + .../src/main/resources/log4j2.xml | 57 ++ .../src/main/resources/sql/user.md | 18 + .../java/com/vonchange/common/AppTest.java | 90 +++ .../src/test/resources/db-init.sql | 21 + 17 files changed, 1223 insertions(+) create mode 100644 spring-data-jdbc-demo/.gitignore create mode 100644 spring-data-jdbc-demo/pom.xml create mode 100644 spring-data-jdbc-demo/src/main/java/com/vonchange/common/App.java create mode 100644 spring-data-jdbc-demo/src/main/java/com/vonchange/common/dao/UserRepository.java create mode 100644 spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/ReqUser.java create mode 100644 spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/UserDTO.java create mode 100644 spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/UserInfoDO.java create mode 100644 spring-data-jdbc-demo/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java create mode 100644 spring-data-jdbc-demo/src/main/resources/application-h2.yml create mode 100644 spring-data-jdbc-demo/src/main/resources/application-mysql.yml create mode 100644 spring-data-jdbc-demo/src/main/resources/application.properties create mode 100644 spring-data-jdbc-demo/src/main/resources/application.yml create mode 100644 spring-data-jdbc-demo/src/main/resources/db-init.sql create mode 100644 spring-data-jdbc-demo/src/main/resources/log4j2.xml create mode 100644 spring-data-jdbc-demo/src/main/resources/sql/user.md create mode 100644 spring-data-jdbc-demo/src/test/java/com/vonchange/common/AppTest.java create mode 100644 spring-data-jdbc-demo/src/test/resources/db-init.sql diff --git a/spring-data-jdbc-demo/.gitignore b/spring-data-jdbc-demo/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/spring-data-jdbc-demo/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/spring-data-jdbc-demo/pom.xml b/spring-data-jdbc-demo/pom.xml new file mode 100644 index 0000000..28d8e63 --- /dev/null +++ b/spring-data-jdbc-demo/pom.xml @@ -0,0 +1,138 @@ + + 4.0.0 + + com.vonchange.common + spring-data-jdbc-mybatis-parent + 2.5.0 + + spring-data-jdbc-demo + jar + + spring-data-jdbc-native + http://maven.apache.org + + 2.7.18 + 2.5.0.1 + 8.0.15 + 2.17.0 + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + org.springframework.boot + spring-boot-starter + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-logging + + + + + + + + + com.vonchange.common + jdbc-mybatis + 2.5.1 + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-log4j2 + + + org.springframework.boot + spring-boot-starter-data-jdbc + 2.1.3.RELEASE + + + + org.projectlombok + lombok + 1.18.6 + + + com.h2database + h2 + 1.4.200 + + + + mysql + mysql-connector-java + 8.0.16 + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + UTF-8 + false + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + org.springframework.boot + spring-boot-maven-plugin + 2.7.18 + + + + + + src/main/resources + + + src/main/java + + **/*.md + + true + + + + diff --git a/spring-data-jdbc-demo/src/main/java/com/vonchange/common/App.java b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/App.java new file mode 100644 index 0000000..42ad8a3 --- /dev/null +++ b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/App.java @@ -0,0 +1,37 @@ +package com.vonchange.common; + +import com.vonchange.jdbc.mybatis.MybatisJdbcTemplate; +import com.vonchange.mybatis.dialect.Dialect; +import com.vonchange.mybatis.dialect.MySQLDialect; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; + +import javax.sql.DataSource; + +/** + * Hello world! + * + */ +@SpringBootApplication +@EnableJdbcRepositories +public class App +{ + + + @Bean + public NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) { + return new MybatisJdbcTemplate(dataSource) { + @Override + protected Dialect dialect() { + return new MySQLDialect(); + } + }; + } + public static void main( String[] args ) + { + SpringApplication.run(App.class, args); + } +} diff --git a/spring-data-jdbc-demo/src/main/java/com/vonchange/common/dao/UserRepository.java b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/dao/UserRepository.java new file mode 100644 index 0000000..509205e --- /dev/null +++ b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/dao/UserRepository.java @@ -0,0 +1,32 @@ +package com.vonchange.common.dao; + +import com.vonchange.common.domain.ReqUser; +import com.vonchange.common.domain.UserDTO; +import com.vonchange.common.domain.UserInfoDO; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jdbc.repository.query.Modifying; +import org.springframework.data.jdbc.repository.query.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface UserRepository extends CrudRepository { + + @Query("user.queryByUserCode") + //@Query("select * from user_info where user_code =:userCode") + List queryByUserCode(@Param("userCode") String userCode); + + Page findByUserCode(String userCode, Pageable pageable); + //@Query("user.queryByBean") + @Query("select * from user_info where user_code = #{user.userCode}") + List queryByBean(@Param("user") ReqUser user); + @Query("user.queryByUserCodes") + //@Query("select * from user_info where user_code in (:userCodes)") + List queryByUserCodes(@Param("userCodes")List userCodes); + List queryByUserName(@Param("userName") String userName); + @Modifying + @Query("update user_info set user_name = #{user.userName} where user_code = #{user.userCode}") + int updateByUserCode(@Param("user") UserDTO user); +} \ No newline at end of file diff --git a/spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/ReqUser.java b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/ReqUser.java new file mode 100644 index 0000000..86c2c41 --- /dev/null +++ b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/ReqUser.java @@ -0,0 +1,16 @@ +package com.vonchange.common.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ReqUser { + private String userCode; +} diff --git a/spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/UserDTO.java b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/UserDTO.java new file mode 100644 index 0000000..85ea0e6 --- /dev/null +++ b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/UserDTO.java @@ -0,0 +1,14 @@ +package com.vonchange.common.domain; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +public class UserDTO { + private String userCode; + private String userName; + private String address; +} diff --git a/spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/UserInfoDO.java b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/UserInfoDO.java new file mode 100644 index 0000000..37cc48c --- /dev/null +++ b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/UserInfoDO.java @@ -0,0 +1,33 @@ +package com.vonchange.common.domain; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Table; + +@Getter +@Setter +@Table("user_info") +@Builder +@AllArgsConstructor +@NoArgsConstructor +@ToString +public class UserInfoDO { + @Id + private Long id; + private String userCode; + //@Column("user_name") + private String userName; + private String mobileNo; + private String address; + // private boolean isValid; + // private Integer status; + // private byte[] headImageData; + + +} diff --git a/spring-data-jdbc-demo/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java b/spring-data-jdbc-demo/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java new file mode 100644 index 0000000..3ef5568 --- /dev/null +++ b/spring-data-jdbc-demo/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java @@ -0,0 +1,649 @@ +/* + * Copyright 2018-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jdbc.core.convert; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.convert.ConverterNotFoundException; +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.convert.CustomConversions; +import org.springframework.data.jdbc.core.mapping.AggregateReference; +import org.springframework.data.jdbc.core.mapping.JdbcValue; +import org.springframework.data.jdbc.support.JdbcUtil; +import org.springframework.data.mapping.Parameter; +import org.springframework.data.mapping.PersistentPropertyAccessor; +import org.springframework.data.mapping.PersistentPropertyPath; +import org.springframework.data.mapping.PreferredConstructor; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator; +import org.springframework.data.mapping.model.ParameterValueProvider; +import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.data.mapping.model.SpELContext; +import org.springframework.data.mapping.model.SpELExpressionEvaluator; +import org.springframework.data.mapping.model.SpELExpressionParameterValueProvider; +import org.springframework.data.relational.core.conversion.BasicRelationalConverter; +import org.springframework.data.relational.core.conversion.RelationalConverter; +import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension; +import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; +import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; +import org.springframework.data.relational.core.sql.IdentifierProcessing; +import org.springframework.data.util.ClassTypeInformation; +import org.springframework.data.util.TypeInformation; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +import java.sql.Array; +import java.sql.JDBCType; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLType; +import java.util.Map; +import java.util.Optional; + +/** + * {@link RelationalConverter} that uses a {@link MappingContext} to apply basic conversion of relational values to + * property values. + *

+ * Conversion is configurable by providing a customized {@link CustomConversions}. + * + * @author Mark Paluch + * @author Jens Schauder + * @author Christoph Strobl + * @author Myeonghyeon Lee + * @author Chirag Tailor + * @see MappingContext + * @see SimpleTypeHolder + * @see CustomConversions + * @since 1.1 + */ +public class BasicJdbcConverter extends BasicRelationalConverter implements JdbcConverter, ApplicationContextAware { + + private static final Log LOG = LogFactory.getLog(BasicJdbcConverter.class); + private static final Converter, Map> ITERABLE_OF_ENTRY_TO_MAP_CONVERTER = new IterableOfEntryToMapConverter(); + + private final JdbcTypeFactory typeFactory; + private final IdentifierProcessing identifierProcessing; + + private final RelationResolver relationResolver; + private SpELContext spELContext; + + /** + * Creates a new {@link BasicRelationalConverter} given {@link MappingContext} and a + * {@link JdbcTypeFactory#unsupported() no-op type factory} throwing {@link UnsupportedOperationException} on type + * creation. Use + * {@link #BasicJdbcConverter(MappingContext, RelationResolver, CustomConversions, JdbcTypeFactory, IdentifierProcessing)} + * (MappingContext, RelationResolver, JdbcTypeFactory)} to convert arrays and large objects into JDBC-specific types. + * + * @param context must not be {@literal null}. + * @param relationResolver used to fetch additional relations from the database. Must not be {@literal null}. + */ + public BasicJdbcConverter( + MappingContext, ? extends RelationalPersistentProperty> context, + RelationResolver relationResolver) { + + super(context, new JdbcCustomConversions()); + + Assert.notNull(relationResolver, "RelationResolver must not be null"); + + this.typeFactory = JdbcTypeFactory.unsupported(); + this.identifierProcessing = IdentifierProcessing.ANSI; + this.relationResolver = relationResolver; + this.spELContext = new SpELContext(ResultSetAccessorPropertyAccessor.INSTANCE); + } + + /** + * Creates a new {@link BasicRelationalConverter} given {@link MappingContext}. + * + * @param context must not be {@literal null}. + * @param relationResolver used to fetch additional relations from the database. Must not be {@literal null}. + * @param typeFactory must not be {@literal null} + * @param identifierProcessing must not be {@literal null} + * @since 2.0 + */ + public BasicJdbcConverter( + MappingContext, ? extends RelationalPersistentProperty> context, + RelationResolver relationResolver, CustomConversions conversions, JdbcTypeFactory typeFactory, + IdentifierProcessing identifierProcessing) { + + super(context, conversions); + + Assert.notNull(typeFactory, "JdbcTypeFactory must not be null"); + Assert.notNull(relationResolver, "RelationResolver must not be null"); + Assert.notNull(identifierProcessing, "IdentifierProcessing must not be null"); + + this.typeFactory = typeFactory; + this.identifierProcessing = identifierProcessing; + this.relationResolver = relationResolver; + this.spELContext = new SpELContext(ResultSetAccessorPropertyAccessor.INSTANCE); + } + + /* + * (non-Javadoc) + * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) + */ + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + this.spELContext = new SpELContext(this.spELContext, applicationContext); + } + + @Nullable + private Class getEntityColumnType(Class type) { + + RelationalPersistentEntity persistentEntity = getMappingContext().getPersistentEntity(type); + + if (persistentEntity == null) { + return null; + } + + RelationalPersistentProperty idProperty = persistentEntity.getIdProperty(); + + if (idProperty == null) { + return null; + } + return getColumnType(idProperty); + } + + private Class getReferenceColumnType(RelationalPersistentProperty property) { + + Class componentType = property.getTypeInformation().getRequiredComponentType().getType(); + RelationalPersistentEntity referencedEntity = getMappingContext().getRequiredPersistentEntity(componentType); + + return getColumnType(referencedEntity.getRequiredIdProperty()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.convert.JdbcConverter#getSqlType(org.springframework.data.relational.core.mapping.RelationalPersistentProperty) + */ + @Override + public SQLType getTargetSqlType(RelationalPersistentProperty property) { + return JdbcUtil.targetSqlTypeFor(getColumnType(property)); + } + + @Override + @Deprecated + public int getSqlType(RelationalPersistentProperty property) { + return JdbcUtil.sqlTypeFor(getColumnType(property)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.convert.JdbcConverter#getColumnType(org.springframework.data.relational.core.mapping.RelationalPersistentProperty) + */ + @Override + public Class getColumnType(RelationalPersistentProperty property) { + return doGetColumnType(property); + } + + private Class doGetColumnType(RelationalPersistentProperty property) { + + if (property.isAssociation()) { + return getReferenceColumnType(property); + } + + if (property.isEntity()) { + Class columnType = getEntityColumnType(property.getActualType()); + + if (columnType != null) { + return columnType; + } + } + + Class componentColumnType = JdbcColumnTypes.INSTANCE.resolvePrimitiveType(property.getActualType()); + + while (componentColumnType.isArray()) { + componentColumnType = componentColumnType.getComponentType(); + } + + if (property.isCollectionLike() && !property.isEntity()) { + return java.lang.reflect.Array.newInstance(componentColumnType, 0).getClass(); + } + + return componentColumnType; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.relational.core.conversion.RelationalConverter#readValue(java.lang.Object, org.springframework.data.util.TypeInformation) + */ + @Override + @Nullable + public Object readValue(@Nullable Object value, TypeInformation type) { + + if (value == null) { + return value; + } + + if (value instanceof Array) { + try { + return super.readValue(((Array) value).getArray(), type); + } catch (SQLException | ConverterNotFoundException e) { + LOG.info("Failed to extract a value of type %s from an Array. Attempting to use standard conversions.", e); + } + } + + return super.readValue(value, type); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.relational.core.conversion.RelationalConverter#writeValue(java.lang.Object, org.springframework.data.util.TypeInformation) + */ + @Override + @Nullable + public Object writeValue(@Nullable Object value, TypeInformation type) { + + if (value == null) { + return null; + } + + return super.writeValue(value, type); + } + + private boolean canWriteAsJdbcValue(@Nullable Object value) { + + if (value == null) { + return true; + } + + if (AggregateReference.class.isAssignableFrom(value.getClass())) { + return canWriteAsJdbcValue(((AggregateReference) value).getId()); + } + + RelationalPersistentEntity persistentEntity = getMappingContext().getPersistentEntity(value.getClass()); + + if (persistentEntity != null) { + + Object id = persistentEntity.getIdentifierAccessor(value).getIdentifier(); + return canWriteAsJdbcValue(id); + } + + if (value instanceof JdbcValue) { + return true; + } + + Optional> customWriteTarget = getConversions().getCustomWriteTarget(value.getClass()); + return customWriteTarget.isPresent() && customWriteTarget.get().isAssignableFrom(JdbcValue.class); + } + + @Override + @Deprecated + public JdbcValue writeJdbcValue(@Nullable Object value, Class columnType, int sqlType) { + return writeJdbcValue(value, columnType, JdbcUtil.jdbcTypeFor(sqlType)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.convert.JdbcConverter#writeValue(java.lang.Object, java.lang.Class, int) + */ + @Override + public JdbcValue writeJdbcValue(@Nullable Object value, Class columnType, SQLType sqlType) { + + JdbcValue jdbcValue = tryToConvertToJdbcValue(value); + if (jdbcValue != null) { + return jdbcValue; + } + + Object convertedValue = writeValue(value, ClassTypeInformation.from(columnType)); + if (convertedValue == null || !convertedValue.getClass().isArray()) { + // @——@转换空值 保留原值 + if(convertedValue==null&&null!=value){convertedValue=value;} + return JdbcValue.of(convertedValue, sqlType); + } + + Class componentType = convertedValue.getClass().getComponentType(); + if (componentType != byte.class && componentType != Byte.class) { + + Object[] objectArray = requireObjectArray(convertedValue); + return JdbcValue.of(typeFactory.createArray(objectArray), JDBCType.ARRAY); + } + + if (componentType == Byte.class) { + convertedValue = ArrayUtils.toPrimitive((Byte[]) convertedValue); + } + + return JdbcValue.of(convertedValue, JDBCType.BINARY); + } + + @Nullable + private JdbcValue tryToConvertToJdbcValue(@Nullable Object value) { + + if (canWriteAsJdbcValue(value)) { + + Object converted = writeValue(value, ClassTypeInformation.from(JdbcValue.class)); + if (converted instanceof JdbcValue) { + return (JdbcValue) converted; + } + } + + return null; + } + + @Override + public T mapRow(RelationalPersistentEntity entity, ResultSet resultSet, Object key) { + return new ReadingContext(new PersistentPropertyPathExtension(getMappingContext(), entity), + new ResultSetAccessor(resultSet), Identifier.empty(), key).mapRow(); + } + + @Override + public T mapRow(PersistentPropertyPathExtension path, ResultSet resultSet, Identifier identifier, Object key) { + return new ReadingContext(path, new ResultSetAccessor(resultSet), identifier, key).mapRow(); + } + + static Object[] requireObjectArray(Object source) { + + Assert.isTrue(source.getClass().isArray(), "Source object is not an array"); + + Class componentType = source.getClass().getComponentType(); + + if (componentType.isPrimitive()) { + if (componentType == boolean.class) { + return ArrayUtils.toObject((boolean[]) source); + } + if (componentType == byte.class) { + return ArrayUtils.toObject((byte[]) source); + } + if (componentType == char.class) { + return ArrayUtils.toObject((char[]) source); + } + if (componentType == double.class) { + return ArrayUtils.toObject((double[]) source); + } + if (componentType == float.class) { + return ArrayUtils.toObject((float[]) source); + } + if (componentType == int.class) { + return ArrayUtils.toObject((int[]) source); + } + if (componentType == long.class) { + return ArrayUtils.toObject((long[]) source); + } + if (componentType == short.class) { + return ArrayUtils.toObject((short[]) source); + } + + throw new IllegalArgumentException("Unsupported component type: " + componentType); + } + return (Object[]) source; + } + + private class ReadingContext { + + private final RelationalPersistentEntity entity; + + private final PersistentPropertyPathExtension rootPath; + private final PersistentPropertyPathExtension path; + private final Identifier identifier; + private final Object key; + + private final JdbcPropertyValueProvider propertyValueProvider; + private final JdbcBackReferencePropertyValueProvider backReferencePropertyValueProvider; + private final ResultSetAccessor accessor; + + @SuppressWarnings("unchecked") + private ReadingContext(PersistentPropertyPathExtension rootPath, ResultSetAccessor accessor, Identifier identifier, + Object key) { + RelationalPersistentEntity entity = (RelationalPersistentEntity) rootPath.getLeafEntity(); + + Assert.notNull(entity, "The rootPath must point to an entity."); + + this.entity = entity; + this.rootPath = rootPath; + this.path = new PersistentPropertyPathExtension(getMappingContext(), this.entity); + this.identifier = identifier; + this.key = key; + this.propertyValueProvider = new JdbcPropertyValueProvider(identifierProcessing, path, accessor); + this.backReferencePropertyValueProvider = new JdbcBackReferencePropertyValueProvider(identifierProcessing, path, + accessor); + this.accessor = accessor; + } + + private ReadingContext(RelationalPersistentEntity entity, PersistentPropertyPathExtension rootPath, + PersistentPropertyPathExtension path, Identifier identifier, Object key, + JdbcPropertyValueProvider propertyValueProvider, + JdbcBackReferencePropertyValueProvider backReferencePropertyValueProvider, ResultSetAccessor accessor) { + this.entity = entity; + this.rootPath = rootPath; + this.path = path; + this.identifier = identifier; + this.key = key; + this.propertyValueProvider = propertyValueProvider; + this.backReferencePropertyValueProvider = backReferencePropertyValueProvider; + this.accessor = accessor; + } + + private ReadingContext extendBy(RelationalPersistentProperty property) { + return new ReadingContext<>( + (RelationalPersistentEntity) getMappingContext().getRequiredPersistentEntity(property.getActualType()), + rootPath.extendBy(property), path.extendBy(property), identifier, key, + propertyValueProvider.extendBy(property), backReferencePropertyValueProvider.extendBy(property), accessor); + } + + T mapRow() { + + RelationalPersistentProperty idProperty = entity.getIdProperty(); + + Object idValue = idProperty == null ? null : readFrom(idProperty); + + return createInstanceInternal(idValue); + } + + private T populateProperties(T instance, @Nullable Object idValue) { + + PersistentPropertyAccessor propertyAccessor = getPropertyAccessor(entity, instance); + PreferredConstructor persistenceConstructor = entity.getPersistenceConstructor(); + + entity.doWithAll(property -> { + + if (persistenceConstructor != null && persistenceConstructor.isConstructorParameter(property)) { + return; + } + + // skip absent simple properties + if (isSimpleProperty(property)) { + + if (!propertyValueProvider.hasProperty(property)) { + return; + } + } + + Object value = readOrLoadProperty(idValue, property); + propertyAccessor.setProperty(property, value); + }); + + return propertyAccessor.getBean(); + } + + @Nullable + private Object readOrLoadProperty(@Nullable Object id, RelationalPersistentProperty property) { + + if ((property.isCollectionLike() && property.isEntity()) || property.isMap()) { + + Iterable allByPath = resolveRelation(id, property); + + return property.isMap() // + ? ITERABLE_OF_ENTRY_TO_MAP_CONVERTER.convert(allByPath) // + : allByPath; + + } else if (property.isEmbedded()) { + return readEmbeddedEntityFrom(id, property); + } else { + return readFrom(property); + } + } + + private Iterable resolveRelation(@Nullable Object id, RelationalPersistentProperty property) { + + Identifier identifier = id == null // + ? this.identifier.withPart(rootPath.getQualifierColumn(), key, Object.class) // + : Identifier.of(rootPath.extendBy(property).getReverseColumnName(), id, Object.class); + + PersistentPropertyPath propertyPath = path.extendBy(property) + .getRequiredPersistentPropertyPath(); + + return relationResolver.findAllByPath(identifier, propertyPath); + } + + /** + * Read a single value or a complete Entity from the {@link ResultSet} passed as an argument. + * + * @param property the {@link RelationalPersistentProperty} for which the value is intended. Must not be + * {@code null}. + * @return the value read from the {@link ResultSet}. May be {@code null}. + */ + @Nullable + private Object readFrom(RelationalPersistentProperty property) { + + if (property.isEntity()) { + return readEntityFrom(property); + } + + Object value = propertyValueProvider.getPropertyValue(property); + return value != null ? readValue(value, property.getTypeInformation()) : null; + } + + @Nullable + private Object readEmbeddedEntityFrom(@Nullable Object idValue, RelationalPersistentProperty property) { + + ReadingContext newContext = extendBy(property); + + if (shouldCreateEmptyEmbeddedInstance(property) || newContext.hasInstanceValues(idValue)) { + return newContext.createInstanceInternal(idValue); + } + + return null; + } + + private boolean shouldCreateEmptyEmbeddedInstance(RelationalPersistentProperty property) { + return property.shouldCreateEmptyEmbedded(); + } + + private boolean hasInstanceValues(@Nullable Object idValue) { + + RelationalPersistentEntity persistentEntity = path.getLeafEntity(); + + Assert.state(persistentEntity != null, "Entity must not be null"); + + for (RelationalPersistentProperty embeddedProperty : persistentEntity) { + + // if the embedded contains Lists, Sets or Maps we consider it non-empty + if (embeddedProperty.isQualified() || embeddedProperty.isAssociation()) { + return true; + } + + Object value = readOrLoadProperty(idValue, embeddedProperty); + if (value != null) { + return true; + } + } + + return false; + } + + @Nullable + @SuppressWarnings("unchecked") + private Object readEntityFrom(RelationalPersistentProperty property) { + + ReadingContext newContext = extendBy(property); + RelationalPersistentEntity entity = getMappingContext().getRequiredPersistentEntity(property.getActualType()); + RelationalPersistentProperty idProperty = entity.getIdProperty(); + + Object idValue; + + if (idProperty != null) { + idValue = newContext.readFrom(idProperty); + } else { + idValue = backReferencePropertyValueProvider.getPropertyValue(property); + } + + if (idValue == null) { + return null; + } + + return newContext.createInstanceInternal(idValue); + } + + private T createInstanceInternal(@Nullable Object idValue) { + + PreferredConstructor persistenceConstructor = entity.getPersistenceConstructor(); + ParameterValueProvider provider; + + if (persistenceConstructor != null && persistenceConstructor.hasParameters()) { + + SpELExpressionEvaluator expressionEvaluator = new DefaultSpELExpressionEvaluator(accessor, spELContext); + provider = new SpELExpressionParameterValueProvider<>(expressionEvaluator, getConversionService(), + new ResultSetParameterValueProvider(idValue, entity)); + } else { + provider = NoOpParameterValueProvider.INSTANCE; + } + + T instance = createInstance(entity, provider::getParameterValue); + + return entity.requiresPropertyPopulation() ? populateProperties(instance, idValue) : instance; + } + + /** + * {@link ParameterValueProvider} that reads a simple property or materializes an object for a + * {@link RelationalPersistentProperty}. + * + * @see #readOrLoadProperty(Object, RelationalPersistentProperty) + * @since 2.1 + */ + private class ResultSetParameterValueProvider implements ParameterValueProvider { + + private final @Nullable Object idValue; + private final RelationalPersistentEntity entity; + + public ResultSetParameterValueProvider(@Nullable Object idValue, RelationalPersistentEntity entity) { + this.idValue = idValue; + this.entity = entity; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mapping.model.ParameterValueProvider#getParameterValue(org.springframework.data.mapping.PreferredConstructor.Parameter) + */ + @Override + @Nullable + public T getParameterValue(Parameter parameter) { + + String parameterName = parameter.getName(); + + Assert.notNull(parameterName, "A constructor parameter name must not be null to be used with Spring Data JDBC"); + + RelationalPersistentProperty property = entity.getRequiredPersistentProperty(parameterName); + return (T) readOrLoadProperty(idValue, property); + } + } + } + + private boolean isSimpleProperty(RelationalPersistentProperty property) { + return !property.isCollectionLike() && !property.isEntity() && !property.isMap() && !property.isEmbedded(); + } + + enum NoOpParameterValueProvider implements ParameterValueProvider { + + INSTANCE; + + @Override + public T getParameterValue(Parameter parameter) { + return null; + } + } + +} diff --git a/spring-data-jdbc-demo/src/main/resources/application-h2.yml b/spring-data-jdbc-demo/src/main/resources/application-h2.yml new file mode 100644 index 0000000..437e131 --- /dev/null +++ b/spring-data-jdbc-demo/src/main/resources/application-h2.yml @@ -0,0 +1,19 @@ +server: + port: 9001 + + +jdbc: + mybatis: + dialect: com.vonchange.mybatis.dialect.H2Dialect + logRead: true + logWrite: true + logFullSql: true + +spring: + datasource: + hikari: + driver-class-name: org.h2.Driver + #jdbc-url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1 MYSQL MODE=MYSQL; + jdbc-url: jdbc:h2:mem:db_users;INIT=RUNSCRIPT FROM 'classpath:db-init.sql' + username: root + password: 123456 diff --git a/spring-data-jdbc-demo/src/main/resources/application-mysql.yml b/spring-data-jdbc-demo/src/main/resources/application-mysql.yml new file mode 100644 index 0000000..a7a71d4 --- /dev/null +++ b/spring-data-jdbc-demo/src/main/resources/application-mysql.yml @@ -0,0 +1,19 @@ +server: + port: 9002 + +jdbc: + mybatis: + isReadAllScopeOpen: false + logRead: true + logWrite: true + logFullSql: true + +spring: + datasource: + hikari: + driver-class-name: com.mysql.cj.jdbc.Driver + #&rewriteBatchedStatements=true&allowMultiQueries=true 1万 3247/245 + jdbc-url: jdbc:mysql://127.0.0.1:3306/jdbc_test?autoReconnect=true&rewriteBatchedStatements=true&allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=CTT + username: root + password: 123456 +# \ No newline at end of file diff --git a/spring-data-jdbc-demo/src/main/resources/application.properties b/spring-data-jdbc-demo/src/main/resources/application.properties new file mode 100644 index 0000000..84af475 --- /dev/null +++ b/spring-data-jdbc-demo/src/main/resources/application.properties @@ -0,0 +1,3 @@ +logging.config= classpath:log4j2.xml + + diff --git a/spring-data-jdbc-demo/src/main/resources/application.yml b/spring-data-jdbc-demo/src/main/resources/application.yml new file mode 100644 index 0000000..22b6c9f --- /dev/null +++ b/spring-data-jdbc-demo/src/main/resources/application.yml @@ -0,0 +1,18 @@ +spring: + profiles: + active: h2 + application: + name: demo + datasource: + hikari: + driver-class-name: com.mysql.cj.jdbc.Driver + jdbc-url: jdbc:mysql://127.0.0.1:3306/jdbc_test?autoReconnect=true&rewriteBatchedStatements=true&allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=CTT + username: root + password: 123456 + maximum-pool-size: 10 + + + + + + diff --git a/spring-data-jdbc-demo/src/main/resources/db-init.sql b/spring-data-jdbc-demo/src/main/resources/db-init.sql new file mode 100644 index 0000000..ab5a6b9 --- /dev/null +++ b/spring-data-jdbc-demo/src/main/resources/db-init.sql @@ -0,0 +1,21 @@ +--SET MODE=MySQL; +SET FOREIGN_KEY_CHECKS=0; +drop table if exists `user_info`; +CREATE TABLE IF NOT EXISTS `user_info` ( + `id` bigint(13) NOT NULL AUTO_INCREMENT COMMENT 'id', + `user_code` varchar(36) DEFAULT NULL COMMENT 'user code', + `user_name` varchar(30) DEFAULT NULL COMMENT 'user name', + `mobile_no` varchar(13) DEFAULT NULL COMMENT 'mobile nubmer', + `address` varchar(20) DEFAULT NULL COMMENT 'address', + `version` int(11) DEFAULT '1' Not NULL COMMENT 'version', + `is_delete` tinyint(1) DEFAULT '0' Not NULL COMMENT 'is delete', + `is_valid` tinyint(1) DEFAULT '0' Not NULL COMMENT 'isValid', + `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + `head_image_data` blob DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + insert into user_info(user_code,user_name,mobile_no,address,create_time) values ('u000','change','000','tang',now()); + insert into user_info(user_code,user_name,mobile_no,address,create_time) values ('u001','Jack','001','hang zhou',now()); + insert into user_info(user_code,user_name,mobile_no,address,create_time,update_time) values ('u002','Elon Reeve Musk','002','Mars',now(),now()); + insert into user_info(user_code,user_name,mobile_no,address,create_time) values ('u003','Bill Gates','003',null,now()); \ No newline at end of file diff --git a/spring-data-jdbc-demo/src/main/resources/log4j2.xml b/spring-data-jdbc-demo/src/main/resources/log4j2.xml new file mode 100644 index 0000000..5e9b388 --- /dev/null +++ b/spring-data-jdbc-demo/src/main/resources/log4j2.xml @@ -0,0 +1,57 @@ + + + + + %d %-5p [%traceId] %c - {} [%T] %m%n + ./logs/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-data-jdbc-demo/src/main/resources/sql/user.md b/spring-data-jdbc-demo/src/main/resources/sql/user.md new file mode 100644 index 0000000..996fd9f --- /dev/null +++ b/spring-data-jdbc-demo/src/main/resources/sql/user.md @@ -0,0 +1,18 @@ +```sql +-- queryByUserCode +select * from user_info where user_code = #{userCode} +``` + +```sql +-- queryByBean +select * from user_info + + [@and user_code = user.userCode] + [@and user_name like user.userName%] + +``` + +```sql +-- queryByUserCodes +select * from user_info where 1=1 [@@and user_code in userCodes] +``` \ No newline at end of file diff --git a/spring-data-jdbc-demo/src/test/java/com/vonchange/common/AppTest.java b/spring-data-jdbc-demo/src/test/java/com/vonchange/common/AppTest.java new file mode 100644 index 0000000..06f5bd7 --- /dev/null +++ b/spring-data-jdbc-demo/src/test/java/com/vonchange/common/AppTest.java @@ -0,0 +1,90 @@ +package com.vonchange.common; + +import com.vonchange.common.dao.UserRepository; +import com.vonchange.common.domain.ReqUser; +import com.vonchange.common.domain.UserDTO; +import com.vonchange.common.domain.UserInfoDO; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.test.annotation.Rollback; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.Arrays; +import java.util.List; + +/** + * Unit test for simple App. + */ +@Slf4j +@SpringBootTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +public class AppTest { + @Resource + private UserRepository userRepository; + @Test + public void queryByUserCode() { + List userInfoDOList= userRepository.queryByUserCode("u001"); + log.info("queryByUserCode:{}",userInfoDOList); + } + @Test + public void queryByUserCodes() { + List userInfoDOList= userRepository.queryByUserCodes(Arrays.asList("u001","u002","u003")); + log.info("queryByUserCodes:{}",userInfoDOList); + } + @Test + public void queryByBean() { + ReqUser userInfoDO=new ReqUser(); + userInfoDO.setUserCode("u001"); + List userInfoDOList= userRepository.queryByBean(userInfoDO); + log.info("queryByBean:{}",userInfoDOList); + } + + @Test + public void findByUserCode() { + Page page= userRepository.findByUserCode("u001", PageRequest.of(0, 1)); + log.info("findByUserCode:{} {}",page,page.getContent()); + } + @Test + public void queryByUserName() { + List userInfoDOList= userRepository.queryByUserName("name:0"); + log.info("queryByUserName:{}",userInfoDOList); + } + @Test + public void findById() { + userRepository.findById(1).ifPresent(item->log.info("findById:{}",item)); + } + @Test + public void updateByUserCode() { + UserDTO userDTO = new UserDTO(); + userDTO.setUserCode("u001"); + userDTO.setUserName("updateByUserCode"); + int num = userRepository.updateByUserCode(userDTO); + log.info("updateByUserCode:{}",num); + List userInfoDOList= userRepository.queryByUserCode("u001"); + log.info("updateByUserCode:{}",userInfoDOList); + } + + @Test + @Rollback + @Transactional + public void insert() { + UserInfoDO userInfoDO =userRepository.save(UserInfoDO.builder().userCode("u009").userName("insert").mobileNo("13888888888").build()); + log.info("insert:{}",userInfoDO); + } + @Test + public void update() { + UserInfoDO userInfoDO =userRepository.save(UserInfoDO.builder().id(1L).userCode("u000001").userName("update").mobileNo("13888888888").build()); + log.info("insert:{}",userInfoDO); + } + + @Test + public void findAll() { + userRepository.findAll().forEach(item->{log.info("item {}",item);}); + } + +} diff --git a/spring-data-jdbc-demo/src/test/resources/db-init.sql b/spring-data-jdbc-demo/src/test/resources/db-init.sql new file mode 100644 index 0000000..77cffcf --- /dev/null +++ b/spring-data-jdbc-demo/src/test/resources/db-init.sql @@ -0,0 +1,21 @@ +--SET MODE=MySQL; +SET FOREIGN_KEY_CHECKS=0; +drop table if exists user_info; +CREATE TABLE IF NOT EXISTS "user_info"( + id bigint NOT NULL auto_increment , + user_code varchar(36) DEFAULT NULL, + user_name varchar(30) DEFAULT NULL, + `mobile_no` varchar(13) DEFAULT NULL , + `address` varchar(20) DEFAULT NULL , + `version` int(11) DEFAULT '1' Not NULL , + `is_delete` tinyint(1) DEFAULT '0' Not NULL , + `is_valid` tinyint(1) DEFAULT '0' Not NULL , + `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + `head_image_data` blob DEFAULT NULL, + PRIMARY KEY (id) +) ; + insert into "user_info"(user_code,user_name,mobile_no,address,create_time) values ('u000','change','000','tang',now()); + insert into "user_info"(user_code,user_name,mobile_no,address,create_time) values ('u001','Jack','001','hang zhou',now()); + insert into "user_info"(user_code,user_name,mobile_no,address,create_time,update_time) values ('u002','Elon Reeve Musk','002','Mars',now(),now()); + insert into "user_info"(user_code,user_name,mobile_no,address,create_time) values ('u003','Bill Gates','003',null,now()); \ No newline at end of file -- Gitee From 28645f108bc8894beb702137e680d9ef56bf208a Mon Sep 17 00:00:00 2001 From: vonchange Date: Tue, 25 Jun 2024 17:00:15 +0800 Subject: [PATCH 05/15] [new] test --- .../src/main/resources/sql/UserInfoRepository.md | 1 + .../vonchange/nine/demo/dao/UserInfoMethodDaoTest.java | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/spring-data-jdbc-mybatis-demo/src/main/resources/sql/UserInfoRepository.md b/spring-data-jdbc-mybatis-demo/src/main/resources/sql/UserInfoRepository.md index 50fb384..2f8da19 100644 --- a/spring-data-jdbc-mybatis-demo/src/main/resources/sql/UserInfoRepository.md +++ b/spring-data-jdbc-mybatis-demo/src/main/resources/sql/UserInfoRepository.md @@ -12,6 +12,7 @@ select [@id column] from user_info [@@and user_code in userCodes] ``` + ``` -- findUserNameByCode select user_name from user_info where user_code = #{userCode} [@id isDelete] diff --git a/spring-data-jdbc-mybatis-demo/src/test/java/com/vonchange/nine/demo/dao/UserInfoMethodDaoTest.java b/spring-data-jdbc-mybatis-demo/src/test/java/com/vonchange/nine/demo/dao/UserInfoMethodDaoTest.java index b9e6b2d..ac2be41 100644 --- a/spring-data-jdbc-mybatis-demo/src/test/java/com/vonchange/nine/demo/dao/UserInfoMethodDaoTest.java +++ b/spring-data-jdbc-mybatis-demo/src/test/java/com/vonchange/nine/demo/dao/UserInfoMethodDaoTest.java @@ -64,6 +64,14 @@ class UserInfoMethodDaoTest { log.info("\nuserInfo {}", JsonUtil.toJson(u)); }); } + + @Test + void findAll() { + userInfoMethodDao + .findAll().forEach(u->{ + log.info("\nuserInfo {}", JsonUtil.toJson(u)); + }); + } @Test void countByExample() { Long num = userInfoMethodDao -- Gitee From 731b3afa17236d2519457aa9534288d54da37ede Mon Sep 17 00:00:00 2001 From: vonchange Date: Tue, 25 Jun 2024 17:00:45 +0800 Subject: [PATCH 06/15] =?UTF-8?q?[new]=20=E6=96=B0=E5=A2=9EmybatisJdbcTemp?= =?UTF-8?q?late=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index b804058..37cec12 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,7 @@ spring-data-jdbc-mybatis-demo mybatis-sql-extend mybatis-sql-extend-test + spring-data-jdbc-demo spring-data-jdbc-mybatis parent pom spring data jdbc with mybatis template dynamic query -- Gitee From b94dc58763c1c2b1fa691319e9c1ff25024fc8d6 Mon Sep 17 00:00:00 2001 From: vonchange Date: Tue, 25 Jun 2024 17:50:47 +0800 Subject: [PATCH 07/15] =?UTF-8?q?[new]=20=E6=96=B0=E5=A2=9EmybatisJdbcTemp?= =?UTF-8?q?late=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jdbc/mybatis/MybatisJdbcTemplate.java | 12 --- .../common/config/MyDialectResolver.java | 87 +++++++++++++++++++ .../main/resources/META-INF/spring.factories | 1 + .../src/main/resources/application-h2.yml | 5 +- .../src/main/resources/db-init.sql | 2 +- .../java/com/vonchange/common/AppTest.java | 3 +- .../src/test/resources/db-init.sql | 34 ++++---- 7 files changed, 110 insertions(+), 34 deletions(-) create mode 100644 spring-data-jdbc-demo/src/main/java/com/vonchange/common/config/MyDialectResolver.java create mode 100644 spring-data-jdbc-demo/src/main/resources/META-INF/spring.factories diff --git a/jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/MybatisJdbcTemplate.java b/jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/MybatisJdbcTemplate.java index fa28473..f882c28 100644 --- a/jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/MybatisJdbcTemplate.java +++ b/jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/MybatisJdbcTemplate.java @@ -17,28 +17,16 @@ import org.springframework.jdbc.support.JdbcUtils; import org.springframework.lang.Nullable; import javax.sql.DataSource; -import java.sql.DatabaseMetaData; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.function.Consumer; public abstract class MybatisJdbcTemplate extends NamedParameterJdbcTemplate { public MybatisJdbcTemplate(DataSource dataSource) { super(dataSource); - DatabaseMetaData metaData = null; - try { - metaData = dataSource.getConnection().getMetaData(); - String name = metaData.getDatabaseProductName().toLowerCase(Locale.ENGLISH); - //h2 - System.out.println("XXXX::"+name); - } catch (SQLException e) { - throw new RuntimeException(e); - } } public MybatisJdbcTemplate(JdbcOperations classicJdbcTemplate) { diff --git a/spring-data-jdbc-demo/src/main/java/com/vonchange/common/config/MyDialectResolver.java b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/config/MyDialectResolver.java new file mode 100644 index 0000000..c16b2df --- /dev/null +++ b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/config/MyDialectResolver.java @@ -0,0 +1,87 @@ +package com.vonchange.common.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.jdbc.core.dialect.JdbcDb2Dialect; +import org.springframework.data.jdbc.core.dialect.JdbcMySqlDialect; +import org.springframework.data.jdbc.core.dialect.JdbcPostgresDialect; +import org.springframework.data.jdbc.core.dialect.JdbcSqlServerDialect; +import org.springframework.data.jdbc.repository.config.DialectResolver; +import org.springframework.data.relational.core.dialect.Dialect; +import org.springframework.data.relational.core.dialect.HsqlDbDialect; +import org.springframework.data.relational.core.dialect.MariaDbDialect; +import org.springframework.data.relational.core.dialect.OracleDialect; +import org.springframework.data.relational.core.sql.IdentifierProcessing; +import org.springframework.jdbc.core.ConnectionCallback; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.util.StringUtils; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.util.Locale; +import java.util.Optional; +@Slf4j +public class MyDialectResolver implements DialectResolver.JdbcDialectProvider { + + @Override + public Optional getDialect(JdbcOperations operations) { + return Optional.ofNullable( + operations.execute((ConnectionCallback) MyDialectResolver::getDialect)); + } + + private static Dialect getDialect(Connection connection) throws SQLException { + DatabaseMetaData metaData = connection.getMetaData(); + String name = metaData.getDatabaseProductName().toLowerCase(Locale.ROOT); + if (name.contains("hsql")) { + return HsqlDbDialect.INSTANCE; + } + if (name.contains("h2")) { + //return JdbcH2Dialect.INSTANCE; + return new JdbcMySqlDialect(getIdentifierProcessing(metaData)); + } + if (name.contains("mysql")) { + return new JdbcMySqlDialect(getIdentifierProcessing(metaData)); + } + if (name.contains("mariadb")) { + return new MariaDbDialect(getIdentifierProcessing(metaData)); + } + if (name.contains("postgresql")) { + return JdbcPostgresDialect.INSTANCE; + } + if (name.contains("microsoft")) { + return JdbcSqlServerDialect.INSTANCE; + } + if (name.contains("db2")) { + return JdbcDb2Dialect.INSTANCE; + } + if (name.contains("oracle")) { + return OracleDialect.INSTANCE; + } + log.info(String.format("Couldn't determine Dialect for \"%s\"", name)); + return null; + } + private static IdentifierProcessing getIdentifierProcessing(DatabaseMetaData metaData) throws SQLException { + + // getIdentifierQuoteString() returns a space " " if identifier quoting is not + // supported. + String quoteString = metaData.getIdentifierQuoteString(); + IdentifierProcessing.Quoting quoting = StringUtils.hasText(quoteString) + ? new IdentifierProcessing.Quoting(quoteString) + : IdentifierProcessing.Quoting.NONE; + + IdentifierProcessing.LetterCasing letterCasing; + // IdentifierProcessing tries to mimic the behavior of unquoted identifiers for their quoted variants. + if (metaData.supportsMixedCaseIdentifiers()) { + letterCasing = IdentifierProcessing.LetterCasing.AS_IS; + } else if (metaData.storesUpperCaseIdentifiers()) { + letterCasing = IdentifierProcessing.LetterCasing.UPPER_CASE; + } else if (metaData.storesLowerCaseIdentifiers()) { + letterCasing = IdentifierProcessing.LetterCasing.LOWER_CASE; + } else { // this shouldn't happen since one of the previous cases should be true. + // But if it does happen, we go with the ANSI default. + letterCasing = IdentifierProcessing.LetterCasing.UPPER_CASE; + } + + return IdentifierProcessing.create(quoting, letterCasing); + } +} \ No newline at end of file diff --git a/spring-data-jdbc-demo/src/main/resources/META-INF/spring.factories b/spring-data-jdbc-demo/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..ea7c971 --- /dev/null +++ b/spring-data-jdbc-demo/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.data.jdbc.repository.config.DialectResolver$JdbcDialectProvider=com.vonchange.common.config.MyDialectResolver \ No newline at end of file diff --git a/spring-data-jdbc-demo/src/main/resources/application-h2.yml b/spring-data-jdbc-demo/src/main/resources/application-h2.yml index 437e131..766ca27 100644 --- a/spring-data-jdbc-demo/src/main/resources/application-h2.yml +++ b/spring-data-jdbc-demo/src/main/resources/application-h2.yml @@ -13,7 +13,8 @@ spring: datasource: hikari: driver-class-name: org.h2.Driver - #jdbc-url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1 MYSQL MODE=MYSQL; - jdbc-url: jdbc:h2:mem:db_users;INIT=RUNSCRIPT FROM 'classpath:db-init.sql' + #jdbc-url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1 MYSQL MODE=MYSQL; DATABASE_TO_LOWER=TRUE; + jdbc-url: jdbc:h2:mem:db_users;DATABASE_TO_LOWER=TRUE;MODE=MYSQL;INIT=RUNSCRIPT FROM 'classpath:db-init.sql' username: root password: 123456 + diff --git a/spring-data-jdbc-demo/src/main/resources/db-init.sql b/spring-data-jdbc-demo/src/main/resources/db-init.sql index ab5a6b9..d88c016 100644 --- a/spring-data-jdbc-demo/src/main/resources/db-init.sql +++ b/spring-data-jdbc-demo/src/main/resources/db-init.sql @@ -1,4 +1,4 @@ ---SET MODE=MySQL; +SET MODE=MySQL; SET FOREIGN_KEY_CHECKS=0; drop table if exists `user_info`; CREATE TABLE IF NOT EXISTS `user_info` ( diff --git a/spring-data-jdbc-demo/src/test/java/com/vonchange/common/AppTest.java b/spring-data-jdbc-demo/src/test/java/com/vonchange/common/AppTest.java index 06f5bd7..96f5d89 100644 --- a/spring-data-jdbc-demo/src/test/java/com/vonchange/common/AppTest.java +++ b/spring-data-jdbc-demo/src/test/java/com/vonchange/common/AppTest.java @@ -6,7 +6,6 @@ import com.vonchange.common.domain.UserDTO; import com.vonchange.common.domain.UserInfoDO; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -22,7 +21,7 @@ import java.util.List; */ @Slf4j @SpringBootTest -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +//@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) public class AppTest { @Resource private UserRepository userRepository; diff --git a/spring-data-jdbc-demo/src/test/resources/db-init.sql b/spring-data-jdbc-demo/src/test/resources/db-init.sql index 77cffcf..d88c016 100644 --- a/spring-data-jdbc-demo/src/test/resources/db-init.sql +++ b/spring-data-jdbc-demo/src/test/resources/db-init.sql @@ -1,21 +1,21 @@ ---SET MODE=MySQL; +SET MODE=MySQL; SET FOREIGN_KEY_CHECKS=0; -drop table if exists user_info; -CREATE TABLE IF NOT EXISTS "user_info"( - id bigint NOT NULL auto_increment , - user_code varchar(36) DEFAULT NULL, - user_name varchar(30) DEFAULT NULL, - `mobile_no` varchar(13) DEFAULT NULL , - `address` varchar(20) DEFAULT NULL , - `version` int(11) DEFAULT '1' Not NULL , - `is_delete` tinyint(1) DEFAULT '0' Not NULL , - `is_valid` tinyint(1) DEFAULT '0' Not NULL , +drop table if exists `user_info`; +CREATE TABLE IF NOT EXISTS `user_info` ( + `id` bigint(13) NOT NULL AUTO_INCREMENT COMMENT 'id', + `user_code` varchar(36) DEFAULT NULL COMMENT 'user code', + `user_name` varchar(30) DEFAULT NULL COMMENT 'user name', + `mobile_no` varchar(13) DEFAULT NULL COMMENT 'mobile nubmer', + `address` varchar(20) DEFAULT NULL COMMENT 'address', + `version` int(11) DEFAULT '1' Not NULL COMMENT 'version', + `is_delete` tinyint(1) DEFAULT '0' Not NULL COMMENT 'is delete', + `is_valid` tinyint(1) DEFAULT '0' Not NULL COMMENT 'isValid', `create_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, `head_image_data` blob DEFAULT NULL, - PRIMARY KEY (id) -) ; - insert into "user_info"(user_code,user_name,mobile_no,address,create_time) values ('u000','change','000','tang',now()); - insert into "user_info"(user_code,user_name,mobile_no,address,create_time) values ('u001','Jack','001','hang zhou',now()); - insert into "user_info"(user_code,user_name,mobile_no,address,create_time,update_time) values ('u002','Elon Reeve Musk','002','Mars',now(),now()); - insert into "user_info"(user_code,user_name,mobile_no,address,create_time) values ('u003','Bill Gates','003',null,now()); \ No newline at end of file + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + insert into user_info(user_code,user_name,mobile_no,address,create_time) values ('u000','change','000','tang',now()); + insert into user_info(user_code,user_name,mobile_no,address,create_time) values ('u001','Jack','001','hang zhou',now()); + insert into user_info(user_code,user_name,mobile_no,address,create_time,update_time) values ('u002','Elon Reeve Musk','002','Mars',now(),now()); + insert into user_info(user_code,user_name,mobile_no,address,create_time) values ('u003','Bill Gates','003',null,now()); \ No newline at end of file -- Gitee From c27ee91fc0f196464abc03baaf90a835c2158a6d Mon Sep 17 00:00:00 2001 From: vonchange Date: Wed, 26 Jun 2024 13:31:40 +0800 Subject: [PATCH 08/15] =?UTF-8?q?[new]=20=E6=96=B0=E5=A2=9EmybatisJdbcTemp?= =?UTF-8?q?late?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/vonchange/jdbc/mybatis/MybatisJdbcTemplate.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/MybatisJdbcTemplate.java b/jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/MybatisJdbcTemplate.java index f882c28..cd48f9c 100644 --- a/jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/MybatisJdbcTemplate.java +++ b/jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/MybatisJdbcTemplate.java @@ -40,13 +40,13 @@ public abstract class MybatisJdbcTemplate extends NamedParameterJdbcTemplate { if(null==sqlParam){ return getPreparedStatementCreatorOriginal(sql,paramSource,customizer); } + Object[] paramObj=sqlParam.getParams().toArray(); List declaredParameters = buildSqlParameterList(sqlParam.getParams()); PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlParam.getSql(),declaredParameters); if (customizer != null) { customizer.accept(pscf); } - Object[] paramObj=sqlParam.getParams().toArray(); - return pscf.newPreparedStatementCreator(paramObj); + return pscf.newPreparedStatementCreator(sqlParam.getSql(),paramObj); } protected PreparedStatementCreator getPreparedStatementCreatorOriginal(String sql, SqlParameterSource paramSource, @Nullable Consumer customizer) { -- Gitee From 03103f993a152af2ea6b5540420cac7c1662fa32 Mon Sep 17 00:00:00 2001 From: vonchange Date: Wed, 26 Jun 2024 13:31:56 +0800 Subject: [PATCH 09/15] =?UTF-8?q?[new]=20=E6=96=B0=E5=A2=9E=E6=96=B9?= =?UTF-8?q?=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatis/dialect/MariaDialect.java | 4 +++ .../mybatis/dialect/PostgresDialect.java | 31 +++++++++++++++++++ recommend.md | 4 +++ 3 files changed, 39 insertions(+) create mode 100644 mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/MariaDialect.java create mode 100644 mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/PostgresDialect.java create mode 100644 recommend.md diff --git a/mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/MariaDialect.java b/mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/MariaDialect.java new file mode 100644 index 0000000..92e4b37 --- /dev/null +++ b/mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/MariaDialect.java @@ -0,0 +1,4 @@ +package com.vonchange.mybatis.dialect; + +public class MariaDialect extends MySQLDialect { +} diff --git a/mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/PostgresDialect.java b/mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/PostgresDialect.java new file mode 100644 index 0000000..80762f4 --- /dev/null +++ b/mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/PostgresDialect.java @@ -0,0 +1,31 @@ +package com.vonchange.mybatis.dialect; + +import com.vonchange.common.util.ConvertUtil; +import com.vonchange.common.util.UtilAll; + +public class PostgresDialect implements Dialect { + @Override + public String getPageSql(String sql, int beginNo, int pageSize) { + return UtilAll.UString.format("{} limit {} OFFSET {} ", sql,ConvertUtil.toString(pageSize), ConvertUtil.toString(beginNo)); + } + + @Override + public int getBigDataFetchSize() { + return 500; + } + + @Override + public int getFetchSize() { + return 500; + } + + @Override + public String getDialogName() { + return "postgres"; + } + + @Override + public LikeTemplate getLikeTemplate() { + return new LikeTemplate(" CONCAT('%',#{{}},'%') "," CONCAT('%',#{{}})"," CONCAT(#{{}},'%') "); + } +} diff --git a/recommend.md b/recommend.md new file mode 100644 index 0000000..f94e6ca --- /dev/null +++ b/recommend.md @@ -0,0 +1,4 @@ + +简单点 开发的方法简单点 繁琐的功能请省略 +数据脱敏 数据缓存 为啥要在ORM框架层实现 +QueryWrapper -- Gitee From c5c0a22ec2759064b75275c5d0d60d55f69cb8c2 Mon Sep 17 00:00:00 2001 From: vonchange Date: Wed, 26 Jun 2024 13:32:27 +0800 Subject: [PATCH 10/15] =?UTF-8?q?[new]=20=E6=96=B0=E5=A2=9EmybatisJdbcTemp?= =?UTF-8?q?late=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/vonchange/common/App.java | 2 -- .../java/com/vonchange/common/domain/UserInfoDO.java | 1 + spring-data-jdbc-demo/src/main/resources/application.yml | 2 +- .../src/test/java/com/vonchange/common/AppTest.java | 9 ++++----- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/spring-data-jdbc-demo/src/main/java/com/vonchange/common/App.java b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/App.java index 42ad8a3..56d8c72 100644 --- a/spring-data-jdbc-demo/src/main/java/com/vonchange/common/App.java +++ b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/App.java @@ -19,8 +19,6 @@ import javax.sql.DataSource; @EnableJdbcRepositories public class App { - - @Bean public NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) { return new MybatisJdbcTemplate(dataSource) { diff --git a/spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/UserInfoDO.java b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/UserInfoDO.java index 37cc48c..bbebea0 100644 --- a/spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/UserInfoDO.java +++ b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/domain/UserInfoDO.java @@ -25,6 +25,7 @@ public class UserInfoDO { private String userName; private String mobileNo; private String address; + private String order; // private boolean isValid; // private Integer status; // private byte[] headImageData; diff --git a/spring-data-jdbc-demo/src/main/resources/application.yml b/spring-data-jdbc-demo/src/main/resources/application.yml index 22b6c9f..3195733 100644 --- a/spring-data-jdbc-demo/src/main/resources/application.yml +++ b/spring-data-jdbc-demo/src/main/resources/application.yml @@ -1,6 +1,6 @@ spring: profiles: - active: h2 + active: mysql application: name: demo datasource: diff --git a/spring-data-jdbc-demo/src/test/java/com/vonchange/common/AppTest.java b/spring-data-jdbc-demo/src/test/java/com/vonchange/common/AppTest.java index 96f5d89..5facfa2 100644 --- a/spring-data-jdbc-demo/src/test/java/com/vonchange/common/AppTest.java +++ b/spring-data-jdbc-demo/src/test/java/com/vonchange/common/AppTest.java @@ -9,8 +9,6 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; -import org.springframework.test.annotation.Rollback; -import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.Arrays; @@ -69,10 +67,11 @@ public class AppTest { } @Test - @Rollback - @Transactional + //@Rollback + //@Transactional public void insert() { - UserInfoDO userInfoDO =userRepository.save(UserInfoDO.builder().userCode("u009").userName("insert").mobileNo("13888888888").build()); + UserInfoDO userInfoDO =userRepository.save(UserInfoDO.builder() + .userCode("u009").userName("insert").order("order").build()); log.info("insert:{}",userInfoDO); } @Test -- Gitee From a22e464e4e27fdcd5ddc3e3708fe5a67d4c99834 Mon Sep 17 00:00:00 2001 From: vonchange Date: Wed, 26 Jun 2024 13:32:44 +0800 Subject: [PATCH 11/15] =?UTF-8?q?[new]=20=E6=B5=8B=E8=AF=95order=20?= =?UTF-8?q?=E6=98=AF=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/vonchange/nine/demo/domain/UserInfoDO.java | 4 ++++ .../com/vonchange/nine/demo/dao/UserInfoMethodDaoTest.java | 1 + .../src/test/resources/application.yml | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/spring-data-jdbc-mybatis-demo/src/main/java/com/vonchange/nine/demo/domain/UserInfoDO.java b/spring-data-jdbc-mybatis-demo/src/main/java/com/vonchange/nine/demo/domain/UserInfoDO.java index 9cac54a..00c7a55 100644 --- a/spring-data-jdbc-mybatis-demo/src/main/java/com/vonchange/nine/demo/domain/UserInfoDO.java +++ b/spring-data-jdbc-mybatis-demo/src/main/java/com/vonchange/nine/demo/domain/UserInfoDO.java @@ -32,4 +32,8 @@ public class UserInfoDO extends BaseDO{ private byte[] headImageData; + @Column(name="`order`") + private String order; + + } diff --git a/spring-data-jdbc-mybatis-demo/src/test/java/com/vonchange/nine/demo/dao/UserInfoMethodDaoTest.java b/spring-data-jdbc-mybatis-demo/src/test/java/com/vonchange/nine/demo/dao/UserInfoMethodDaoTest.java index ac2be41..0591073 100644 --- a/spring-data-jdbc-mybatis-demo/src/test/java/com/vonchange/nine/demo/dao/UserInfoMethodDaoTest.java +++ b/spring-data-jdbc-mybatis-demo/src/test/java/com/vonchange/nine/demo/dao/UserInfoMethodDaoTest.java @@ -129,6 +129,7 @@ class UserInfoMethodDaoTest { userInfoDO.setUserCode("L001"); userInfoDO.setUserName("Bruce Lee"); userInfoDO.setValid(true); + userInfoDO.setOrder("order1111"); //userInfoDO.setHeadImageData(IOUtils.toByteArray(UtilAll.UFile.getClassResource("db-init.sql"))); userInfoMethodDao.insert(userInfoDO); log.info("\ninsert {}",JsonUtil.toJson(userInfoDO)); diff --git a/spring-data-jdbc-mybatis-demo/src/test/resources/application.yml b/spring-data-jdbc-mybatis-demo/src/test/resources/application.yml index 22b6c9f..3195733 100644 --- a/spring-data-jdbc-mybatis-demo/src/test/resources/application.yml +++ b/spring-data-jdbc-mybatis-demo/src/test/resources/application.yml @@ -1,6 +1,6 @@ spring: profiles: - active: h2 + active: mysql application: name: demo datasource: -- Gitee From 2fb1cbb28c6d465a73a611c2f73db60bda4a9830 Mon Sep 17 00:00:00 2001 From: vonchange Date: Wed, 26 Jun 2024 14:26:47 +0800 Subject: [PATCH 12/15] [new] test --- spring-data-jdbc-demo/pom.xml | 33 ++++++------------- .../src/main/resources/application.yml | 2 +- .../src/main/resources/db-init.sql | 21 ------------ .../src/test/resources/db-init.sql | 1 + spring-data-jdbc-mybatis-demo/pom.xml | 24 ++++---------- .../src/test/resources/application.yml | 2 +- .../src/test/resources/db-init.sql | 1 + 7 files changed, 21 insertions(+), 63 deletions(-) delete mode 100644 spring-data-jdbc-demo/src/main/resources/db-init.sql diff --git a/spring-data-jdbc-demo/pom.xml b/spring-data-jdbc-demo/pom.xml index 28d8e63..b98702b 100644 --- a/spring-data-jdbc-demo/pom.xml +++ b/spring-data-jdbc-demo/pom.xml @@ -41,6 +41,11 @@ + + org.projectlombok + lombok + 1.18.6 + com.vonchange.common jdbc-mybatis @@ -48,7 +53,7 @@ org.springframework.boot - spring-boot-starter-web + spring-boot-starter org.springframework.boot @@ -57,35 +62,17 @@ org.springframework.boot spring-boot-starter-data-jdbc - 2.1.3.RELEASE - - org.projectlombok - lombok - 1.18.6 + mysql + mysql-connector-java + 8.0.16 com.h2database h2 1.4.200 - - - - mysql - mysql-connector-java - 8.0.16 + test org.springframework.boot diff --git a/spring-data-jdbc-demo/src/main/resources/application.yml b/spring-data-jdbc-demo/src/main/resources/application.yml index 3195733..22b6c9f 100644 --- a/spring-data-jdbc-demo/src/main/resources/application.yml +++ b/spring-data-jdbc-demo/src/main/resources/application.yml @@ -1,6 +1,6 @@ spring: profiles: - active: mysql + active: h2 application: name: demo datasource: diff --git a/spring-data-jdbc-demo/src/main/resources/db-init.sql b/spring-data-jdbc-demo/src/main/resources/db-init.sql deleted file mode 100644 index d88c016..0000000 --- a/spring-data-jdbc-demo/src/main/resources/db-init.sql +++ /dev/null @@ -1,21 +0,0 @@ -SET MODE=MySQL; -SET FOREIGN_KEY_CHECKS=0; -drop table if exists `user_info`; -CREATE TABLE IF NOT EXISTS `user_info` ( - `id` bigint(13) NOT NULL AUTO_INCREMENT COMMENT 'id', - `user_code` varchar(36) DEFAULT NULL COMMENT 'user code', - `user_name` varchar(30) DEFAULT NULL COMMENT 'user name', - `mobile_no` varchar(13) DEFAULT NULL COMMENT 'mobile nubmer', - `address` varchar(20) DEFAULT NULL COMMENT 'address', - `version` int(11) DEFAULT '1' Not NULL COMMENT 'version', - `is_delete` tinyint(1) DEFAULT '0' Not NULL COMMENT 'is delete', - `is_valid` tinyint(1) DEFAULT '0' Not NULL COMMENT 'isValid', - `create_time` datetime DEFAULT NULL, - `update_time` datetime DEFAULT NULL, - `head_image_data` blob DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - insert into user_info(user_code,user_name,mobile_no,address,create_time) values ('u000','change','000','tang',now()); - insert into user_info(user_code,user_name,mobile_no,address,create_time) values ('u001','Jack','001','hang zhou',now()); - insert into user_info(user_code,user_name,mobile_no,address,create_time,update_time) values ('u002','Elon Reeve Musk','002','Mars',now(),now()); - insert into user_info(user_code,user_name,mobile_no,address,create_time) values ('u003','Bill Gates','003',null,now()); \ No newline at end of file diff --git a/spring-data-jdbc-demo/src/test/resources/db-init.sql b/spring-data-jdbc-demo/src/test/resources/db-init.sql index d88c016..ec5671d 100644 --- a/spring-data-jdbc-demo/src/test/resources/db-init.sql +++ b/spring-data-jdbc-demo/src/test/resources/db-init.sql @@ -7,6 +7,7 @@ CREATE TABLE IF NOT EXISTS `user_info` ( `user_name` varchar(30) DEFAULT NULL COMMENT 'user name', `mobile_no` varchar(13) DEFAULT NULL COMMENT 'mobile nubmer', `address` varchar(20) DEFAULT NULL COMMENT 'address', + `order` varchar(50) DEFAULT NULL COMMENT 'order', `version` int(11) DEFAULT '1' Not NULL COMMENT 'version', `is_delete` tinyint(1) DEFAULT '0' Not NULL COMMENT 'is delete', `is_valid` tinyint(1) DEFAULT '0' Not NULL COMMENT 'isValid', diff --git a/spring-data-jdbc-mybatis-demo/pom.xml b/spring-data-jdbc-mybatis-demo/pom.xml index 4450327..3617e9d 100644 --- a/spring-data-jdbc-mybatis-demo/pom.xml +++ b/spring-data-jdbc-mybatis-demo/pom.xml @@ -9,7 +9,7 @@ spring-data-jdbc-mybatis-demo 测试 2.7.18 - 2.5.0.1 + 2.5.0.3 8.0.15 2.17.0 @@ -36,6 +36,11 @@ + + org.projectlombok + lombok + 1.18.6 + com.vonchange.common spring-data-jdbc-mybatis @@ -43,11 +48,7 @@ org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-undertow + spring-boot-starter org.springframework.boot @@ -58,11 +59,6 @@ commons-io 2.5 - - org.projectlombok - lombok - 1.18.6 - com.fasterxml.jackson.datatype jackson-datatype-jsr310 @@ -93,12 +89,6 @@ spring-boot-starter-test test - diff --git a/spring-data-jdbc-mybatis-demo/src/test/resources/application.yml b/spring-data-jdbc-mybatis-demo/src/test/resources/application.yml index 3195733..22b6c9f 100644 --- a/spring-data-jdbc-mybatis-demo/src/test/resources/application.yml +++ b/spring-data-jdbc-mybatis-demo/src/test/resources/application.yml @@ -1,6 +1,6 @@ spring: profiles: - active: mysql + active: h2 application: name: demo datasource: diff --git a/spring-data-jdbc-mybatis-demo/src/test/resources/db-init.sql b/spring-data-jdbc-mybatis-demo/src/test/resources/db-init.sql index d88c016..ec5671d 100644 --- a/spring-data-jdbc-mybatis-demo/src/test/resources/db-init.sql +++ b/spring-data-jdbc-mybatis-demo/src/test/resources/db-init.sql @@ -7,6 +7,7 @@ CREATE TABLE IF NOT EXISTS `user_info` ( `user_name` varchar(30) DEFAULT NULL COMMENT 'user name', `mobile_no` varchar(13) DEFAULT NULL COMMENT 'mobile nubmer', `address` varchar(20) DEFAULT NULL COMMENT 'address', + `order` varchar(50) DEFAULT NULL COMMENT 'order', `version` int(11) DEFAULT '1' Not NULL COMMENT 'version', `is_delete` tinyint(1) DEFAULT '0' Not NULL COMMENT 'is delete', `is_valid` tinyint(1) DEFAULT '0' Not NULL COMMENT 'isValid', -- Gitee From ef490da125f46609dd3d2385c93add37efffa08b Mon Sep 17 00:00:00 2001 From: vonchange Date: Wed, 26 Jun 2024 14:36:34 +0800 Subject: [PATCH 13/15] [new] 2.5.1 --- jdbc-mybatis/pom.xml | 2 +- mybatis-sql-extend/pom.xml | 2 +- .../mybatis/dialect/{H2Dialect.java => H2MySqlDialect.java} | 2 +- spring-data-jdbc-demo/pom.xml | 4 ++-- spring-data-jdbc-demo/src/main/resources/application-h2.yml | 2 +- spring-data-jdbc-mybatis-demo/pom.xml | 2 +- .../src/test/resources/application-h2.yml | 2 +- spring-data-jdbc-mybatis/pom.xml | 6 +++--- .../jdbc/mybatis/core/config/JdbcConfiguration.java | 2 +- .../jdbc/mybatis/core/support/JdbcQueryLookupStrategy.java | 2 +- .../jdbc/mybatis/core/support/JdbcRepositoryFactory.java | 2 +- .../jdbc/mybatis/core/support/JdbcRepositoryQuery.java | 2 +- .../jdbc/mybatis/core/support/SimpleJdbcRepository.java | 2 +- 13 files changed, 16 insertions(+), 16 deletions(-) rename mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/{H2Dialect.java => H2MySqlDialect.java} (94%) diff --git a/jdbc-mybatis/pom.xml b/jdbc-mybatis/pom.xml index 05aec99..a9b59e4 100644 --- a/jdbc-mybatis/pom.xml +++ b/jdbc-mybatis/pom.xml @@ -14,7 +14,7 @@ com.vonchange.common mybatis-sql-extend - 2.5.0.1 + 2.5.1 com.vonchange.common diff --git a/mybatis-sql-extend/pom.xml b/mybatis-sql-extend/pom.xml index 9813bf4..e79557d 100644 --- a/mybatis-sql-extend/pom.xml +++ b/mybatis-sql-extend/pom.xml @@ -9,7 +9,7 @@ 4.0.0 mybatis-sql-extend - 2.5.0.1 + 2.5.1 com.vonchange.common diff --git a/mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/H2Dialect.java b/mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/H2MySqlDialect.java similarity index 94% rename from mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/H2Dialect.java rename to mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/H2MySqlDialect.java index ee29ff4..cb7025f 100644 --- a/mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/H2Dialect.java +++ b/mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/H2MySqlDialect.java @@ -10,7 +10,7 @@ import com.vonchange.common.util.UtilAll; * @author von_change@163.com * 2015-6-14 下午12:47:21 */ -public class H2Dialect implements Dialect { +public class H2MySqlDialect implements Dialect { @Override public String getPageSql(String sql, int beginNo, int pageSize) { diff --git a/spring-data-jdbc-demo/pom.xml b/spring-data-jdbc-demo/pom.xml index b98702b..ddce2b2 100644 --- a/spring-data-jdbc-demo/pom.xml +++ b/spring-data-jdbc-demo/pom.xml @@ -13,7 +13,7 @@ http://maven.apache.org 2.7.18 - 2.5.0.1 + 2.5.1 8.0.15 2.17.0 @@ -49,7 +49,7 @@ com.vonchange.common jdbc-mybatis - 2.5.1 + ${jdbc.mybatis} org.springframework.boot diff --git a/spring-data-jdbc-demo/src/main/resources/application-h2.yml b/spring-data-jdbc-demo/src/main/resources/application-h2.yml index 766ca27..076a624 100644 --- a/spring-data-jdbc-demo/src/main/resources/application-h2.yml +++ b/spring-data-jdbc-demo/src/main/resources/application-h2.yml @@ -4,7 +4,7 @@ server: jdbc: mybatis: - dialect: com.vonchange.mybatis.dialect.H2Dialect + dialect: com.vonchange.mybatis.dialect.H2MysqlDialect logRead: true logWrite: true logFullSql: true diff --git a/spring-data-jdbc-mybatis-demo/pom.xml b/spring-data-jdbc-mybatis-demo/pom.xml index 3617e9d..29f2d70 100644 --- a/spring-data-jdbc-mybatis-demo/pom.xml +++ b/spring-data-jdbc-mybatis-demo/pom.xml @@ -9,7 +9,7 @@ spring-data-jdbc-mybatis-demo 测试 2.7.18 - 2.5.0.3 + 2.5.1 8.0.15 2.17.0 diff --git a/spring-data-jdbc-mybatis-demo/src/test/resources/application-h2.yml b/spring-data-jdbc-mybatis-demo/src/test/resources/application-h2.yml index 355d4bc..275e2ca 100644 --- a/spring-data-jdbc-mybatis-demo/src/test/resources/application-h2.yml +++ b/spring-data-jdbc-mybatis-demo/src/test/resources/application-h2.yml @@ -4,7 +4,7 @@ server: jdbc: mybatis: - dialect: com.vonchange.mybatis.dialect.H2Dialect + dialect: com.vonchange.mybatis.dialect.H2MysqlDialect logRead: true logWrite: true logFullSql: true diff --git a/spring-data-jdbc-mybatis/pom.xml b/spring-data-jdbc-mybatis/pom.xml index 92bf06f..aec10f8 100644 --- a/spring-data-jdbc-mybatis/pom.xml +++ b/spring-data-jdbc-mybatis/pom.xml @@ -8,7 +8,7 @@ 2.5.0 spring-data-jdbc-mybatis - 2.5.0.3 + 2.5.1 spring-data-jdbc-mybatis spring data jdbc with mybatis template dynamic query @@ -17,13 +17,13 @@ 2.1.5.RELEASE 5.1.5.RELEASE 8.0.15 - 2.5.0.1 + 2.5.1 com.vonchange.common jdbc-mybatis - ${mybatis.mini} + ${jdbc.mybatis} org.springframework.data diff --git a/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/config/JdbcConfiguration.java b/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/config/JdbcConfiguration.java index eb89392..95412dc 100644 --- a/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/config/JdbcConfiguration.java +++ b/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/config/JdbcConfiguration.java @@ -16,8 +16,8 @@ package com.vonchange.jdbc.mybatis.core.config; import com.vonchange.common.util.exception.ErrorMsg; +import com.vonchange.jdbc.client.CrudClient; import com.vonchange.jdbc.config.ConstantJdbc; -import com.vonchange.jdbc.core.CrudClient; import com.vonchange.jdbc.model.DataSourceWrapper; import com.vonchange.mybatis.dialect.Dialect; import com.vonchange.mybatis.exception.EnumJdbcErrorCode; diff --git a/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcQueryLookupStrategy.java b/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcQueryLookupStrategy.java index ab92d7f..8fb81fe 100644 --- a/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcQueryLookupStrategy.java +++ b/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcQueryLookupStrategy.java @@ -15,8 +15,8 @@ */ package com.vonchange.jdbc.mybatis.core.support; +import com.vonchange.jdbc.client.CrudClient; import com.vonchange.jdbc.config.ConstantJdbc; -import com.vonchange.jdbc.core.CrudClient; import com.vonchange.jdbc.core.CrudUtil; import com.vonchange.jdbc.mybatis.core.config.ConfigInfo; import com.vonchange.jdbc.mybatis.core.config.JdbcConfiguration; diff --git a/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcRepositoryFactory.java b/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcRepositoryFactory.java index d40a842..7e28afe 100644 --- a/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcRepositoryFactory.java +++ b/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcRepositoryFactory.java @@ -17,8 +17,8 @@ package com.vonchange.jdbc.mybatis.core.support; import com.vonchange.common.util.MarkdownUtil; +import com.vonchange.jdbc.client.CrudClient; import com.vonchange.jdbc.config.ConstantJdbc; -import com.vonchange.jdbc.core.CrudClient; import com.vonchange.jdbc.core.CrudUtil; import com.vonchange.jdbc.mybatis.core.config.ConfigInfo; import com.vonchange.jdbc.mybatis.core.config.JdbcConfiguration; diff --git a/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcRepositoryQuery.java b/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcRepositoryQuery.java index 79e57b8..d45084e 100644 --- a/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcRepositoryQuery.java +++ b/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/JdbcRepositoryQuery.java @@ -18,8 +18,8 @@ package com.vonchange.jdbc.mybatis.core.support; import com.vonchange.common.util.ClazzUtils; import com.vonchange.common.util.MarkdownUtil; import com.vonchange.common.util.StringPool; +import com.vonchange.jdbc.client.CrudClient; import com.vonchange.jdbc.config.ConstantJdbc; -import com.vonchange.jdbc.core.CrudClient; import com.vonchange.jdbc.model.SqlParam; import com.vonchange.jdbc.mybatis.core.config.BindParameterWrapper; import com.vonchange.jdbc.mybatis.core.config.ConfigInfo; diff --git a/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/SimpleJdbcRepository.java b/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/SimpleJdbcRepository.java index 26a983a..3463c57 100644 --- a/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/SimpleJdbcRepository.java +++ b/spring-data-jdbc-mybatis/src/main/java/com/vonchange/jdbc/mybatis/core/support/SimpleJdbcRepository.java @@ -18,9 +18,9 @@ package com.vonchange.jdbc.mybatis.core.support; import com.vonchange.common.util.Assert; import com.vonchange.common.util.JsonUtil; import com.vonchange.common.util.bean.BeanUtil; +import com.vonchange.jdbc.client.CrudClient; import com.vonchange.jdbc.client.JdbcClient; import com.vonchange.jdbc.config.EnumNameQueryType; -import com.vonchange.jdbc.core.CrudClient; import com.vonchange.jdbc.model.EntityInfo; import com.vonchange.jdbc.model.SqlParam; import com.vonchange.jdbc.mybatis.core.config.ConfigInfo; -- Gitee From 20308509f2319858bdf3327720ff75913f990384 Mon Sep 17 00:00:00 2001 From: vonchange Date: Wed, 26 Jun 2024 15:08:26 +0800 Subject: [PATCH 14/15] [new] 2.5.1 --- mybatis-sql-extend-test/pom.xml | 2 +- .../mybatis/dialect/H2MySqlDialect.java | 27 ++----------------- spring-data-jdbc-mybatis-demo/pom.xml | 4 +-- .../nine/demo/dao/UserInfoCrudClientDao.java | 3 ++- .../nine/demo/dao/CrudClientTest.java | 2 +- .../src/test/resources/application-h2.yml | 2 +- 6 files changed, 9 insertions(+), 31 deletions(-) diff --git a/mybatis-sql-extend-test/pom.xml b/mybatis-sql-extend-test/pom.xml index ae38ed9..479f41b 100644 --- a/mybatis-sql-extend-test/pom.xml +++ b/mybatis-sql-extend-test/pom.xml @@ -14,7 +14,7 @@ mybatis-sql-extend-test 2.5.0 - 2.5.0 + 2.5.1 8.0.15 diff --git a/mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/H2MySqlDialect.java b/mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/H2MySqlDialect.java index cb7025f..515055f 100644 --- a/mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/H2MySqlDialect.java +++ b/mybatis-sql-extend/src/main/java/com/vonchange/mybatis/dialect/H2MySqlDialect.java @@ -1,24 +1,6 @@ package com.vonchange.mybatis.dialect; - -import com.vonchange.common.util.ConvertUtil; -import com.vonchange.common.util.UtilAll; - - -/** - *mysql方言 - * @author von_change@163.com - * 2015-6-14 下午12:47:21 - */ -public class H2MySqlDialect implements Dialect { - - @Override - public String getPageSql(String sql, int beginNo, int pageSize) { - return UtilAll.UString.format("{} limit {},{} ", sql, ConvertUtil.toString(beginNo), ConvertUtil.toString(pageSize)); - } - - - +public class H2MySqlDialect extends MySQLDialect { @Override public int getBigDataFetchSize() { return 500; @@ -31,11 +13,6 @@ public class H2MySqlDialect implements Dialect { @Override public String getDialogName() { - return "h2"; - } - - @Override - public LikeTemplate getLikeTemplate() { - return new LikeTemplate(" CONCAT('%',#{{}},'%') "," CONCAT('%',#{{}})"," CONCAT(#{{}},'%') "); + return "h2-mysql"; } } diff --git a/spring-data-jdbc-mybatis-demo/pom.xml b/spring-data-jdbc-mybatis-demo/pom.xml index 29f2d70..170e4fc 100644 --- a/spring-data-jdbc-mybatis-demo/pom.xml +++ b/spring-data-jdbc-mybatis-demo/pom.xml @@ -9,7 +9,7 @@ spring-data-jdbc-mybatis-demo 测试 2.7.18 - 2.5.1 + 2.5.1 8.0.15 2.17.0 @@ -44,7 +44,7 @@ com.vonchange.common spring-data-jdbc-mybatis - ${spring.jdbc.mybatis} + ${jdbc.mybatis} org.springframework.boot diff --git a/spring-data-jdbc-mybatis-demo/src/main/java/com/vonchange/nine/demo/dao/UserInfoCrudClientDao.java b/spring-data-jdbc-mybatis-demo/src/main/java/com/vonchange/nine/demo/dao/UserInfoCrudClientDao.java index d84497b..2c87e7e 100644 --- a/spring-data-jdbc-mybatis-demo/src/main/java/com/vonchange/nine/demo/dao/UserInfoCrudClientDao.java +++ b/spring-data-jdbc-mybatis-demo/src/main/java/com/vonchange/nine/demo/dao/UserInfoCrudClientDao.java @@ -1,6 +1,7 @@ package com.vonchange.nine.demo.dao; -import com.vonchange.jdbc.core.CrudClient; + +import com.vonchange.jdbc.client.CrudClient; import com.vonchange.nine.demo.domain.UserInfoDO; import lombok.AllArgsConstructor; import org.springframework.stereotype.Repository; diff --git a/spring-data-jdbc-mybatis-demo/src/test/java/com/vonchange/nine/demo/dao/CrudClientTest.java b/spring-data-jdbc-mybatis-demo/src/test/java/com/vonchange/nine/demo/dao/CrudClientTest.java index 329aaf9..cd1aa34 100644 --- a/spring-data-jdbc-mybatis-demo/src/test/java/com/vonchange/nine/demo/dao/CrudClientTest.java +++ b/spring-data-jdbc-mybatis-demo/src/test/java/com/vonchange/nine/demo/dao/CrudClientTest.java @@ -1,7 +1,7 @@ package com.vonchange.nine.demo.dao; import com.vonchange.common.util.JsonUtil; -import com.vonchange.jdbc.core.CrudClient; +import com.vonchange.jdbc.client.CrudClient; import com.vonchange.jdbc.mapper.AbstractPageWork; import com.vonchange.nine.demo.domain.UserInfoDO; import lombok.extern.slf4j.Slf4j; diff --git a/spring-data-jdbc-mybatis-demo/src/test/resources/application-h2.yml b/spring-data-jdbc-mybatis-demo/src/test/resources/application-h2.yml index 275e2ca..af57019 100644 --- a/spring-data-jdbc-mybatis-demo/src/test/resources/application-h2.yml +++ b/spring-data-jdbc-mybatis-demo/src/test/resources/application-h2.yml @@ -4,7 +4,7 @@ server: jdbc: mybatis: - dialect: com.vonchange.mybatis.dialect.H2MysqlDialect + dialect: com.vonchange.mybatis.dialect.H2MySqlDialect logRead: true logWrite: true logFullSql: true -- Gitee From c210dd4a9378b8474a504e2e268bdcb38d056d3a Mon Sep 17 00:00:00 2001 From: vonchange Date: Wed, 26 Jun 2024 16:06:18 +0800 Subject: [PATCH 15/15] [new] update readme --- README.zh-CN.md | 26 +++++++++- recommend.md | 48 +++++++++++++++++-- .../main/java/com/vonchange/common/App.java | 8 +--- 3 files changed, 71 insertions(+), 11 deletions(-) diff --git a/README.zh-CN.md b/README.zh-CN.md index fd67f76..d59dc05 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -7,8 +7,30 @@ [![](https://gitee.com/vonchange/spring-data-jdbc-mybatis/badge/star.svg?theme=dark) ](https://gitee.com/vonchange/spring-data-jdbc-mybatis) -**spring data jdbc 扩展 mybatis 动态sql能力** -## What Is This? +**简单点 开发的方法简单点 繁琐的功能请省略 你有不是个AI** +## spring data jdbc 扩展 mybatis 动态sql能力 +### spring data jdbc官方直接 扩展 mybatis动态sql能力 + +使用方式和官方教程一直 引入spring-boot-starter-data-jdbc 即可 +只需要配置魔改的NamedParameterJdbcTemplate 即可 +``` + @Bean + public NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) {return new MybatisJdbcTemplate(dataSource) {@Override + protected Dialect dialect() {return new MySQLDialect();} + }; + } +``` +@Query 的ID 是user.md里面ID是queryByUserCode的sql片段 +``` + @Query("user.queryByUserCode") + List queryByUserCode(@Param("userCode") String userCode); +``` +具体使用参考spring-data-jdbc-demo +但是 @Query spring 6(jdk17以上) 以上才支持SPEL 不支持实体参数 +通过改代码可以解决(支持mybatis版本的) 但有代码侵入性 +无法直接 根据方法名 自动查找sql片段 + +### 更推荐自研版本spring data jdbc扩展 mybatis动态sql能力 * 底层 jdbcTemplate 复杂SQL才需要mybatis动态模板能力 无QueryDSL 提供crudClient 和jdbcClient * 和spring data jdbc一样的追求简单,使用jdbcTemplate,调用jdbc。不提供缓存、延迟加载、QueryDSL等JPA或mybatis的许多特性。一个简单、有限、固执己见的ORM diff --git a/recommend.md b/recommend.md index f94e6ca..de90195 100644 --- a/recommend.md +++ b/recommend.md @@ -1,4 +1,46 @@ + +- [欢迎点击star github地址](https://github.com/VonChange/spring-data-jdbc-mybatis) +- [欢迎点击star gitee地址](https://gitee.com/vonchange/spring-data-jdbc-mybatis) -简单点 开发的方法简单点 繁琐的功能请省略 -数据脱敏 数据缓存 为啥要在ORM框架层实现 -QueryWrapper +**简单点 开发的方法简单点 繁琐的功能请省略 你有不是个AI** +### spring data jdbc 扩展 mybatis 动态sql能力 +##### spring data jdbc官方直接 扩展 mybatis动态sql能力 + +使用方式和官方教程一直 引入spring-boot-starter-data-jdbc 即可 +只需要配置魔改的NamedParameterJdbcTemplate 即可 +``` + @Bean + public NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) {return new MybatisJdbcTemplate(dataSource) {@Override + protected Dialect dialect() {return new MySQLDialect();} + }; + } +``` +@Query 的ID 是user.md里面ID是queryByUserCode的sql片段 +``` + @Query("user.queryByUserCode") + List queryByUserCode(@Param("userCode") String userCode); +``` +具体使用参考spring-data-jdbc-demo +但是 @Query spring 6(jdk17以上) 以上才支持SPEL 不支持实体参数 +通过改代码可以解决(支持mybatis版本的) 但有代码侵入性 +无法直接 根据方法名 自动查找sql片段 + +##### 仿spring 6+ jdbcClient实现 更推荐crudClient +##### 更推荐自研版本spring data jdbc扩展 mybatis动态sql能力 +* 底层 jdbcTemplate 复杂SQL才需要mybatis动态模板能力 无QueryDSL/queryMapper 提供crudClient 和jdbcClient + +* 和spring data jdbc一样的追求简单,使用jdbcTemplate,调用jdbc。不提供缓存、延迟加载、QueryDSL等JPA或mybatis的许多特性。一个简单、有限的ORM + +* 扩展并兼容mybatis动态sql能力(不依赖mybatis!提取了动态sql代码),可以应对复杂sql,如果换其他模板引擎(后续可以加)也是可以的,但有学习成本 + +* 复杂的SQL写在Markdown的代码片段中,不提供@Query和QueryDSL写法,但按方法名查找和扩展的findByExample可以应付大部分单表查询需求 + +* 简化mybatis动态sql写法 [easy-dynamic-sql.md](easy-dynamic-sql.md) + +##### 这真是缺点? + +- 缺点一:无QueryDSL/QueryWrapper 我是个懒人 既然service层里可以写QueryWrapper 为啥不可以写在service 为啥要重用? + 要我独立个dao/Repository把数据层下放?想啥呢?! + 我这个框架就只能在dao/Repository层 写确实太麻烦了 复杂的sql还得建个markdown文件 +- 缺点二:没有数据缓存 审计 数据脱敏 IService接口 就不能替我做了吗 非得在应用层实现 +其实我这给了spring缓存框架等用武之地 自己实现可以增加代码量和工作量 在还没被ai替代之前 薅羊毛 \ No newline at end of file diff --git a/spring-data-jdbc-demo/src/main/java/com/vonchange/common/App.java b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/App.java index 56d8c72..a470210 100644 --- a/spring-data-jdbc-demo/src/main/java/com/vonchange/common/App.java +++ b/spring-data-jdbc-demo/src/main/java/com/vonchange/common/App.java @@ -20,12 +20,8 @@ import javax.sql.DataSource; public class App { @Bean - public NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) { - return new MybatisJdbcTemplate(dataSource) { - @Override - protected Dialect dialect() { - return new MySQLDialect(); - } + public NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) {return new MybatisJdbcTemplate(dataSource) {@Override + protected Dialect dialect() {return new MySQLDialect();} }; } public static void main( String[] args ) -- Gitee