From 581007e1da59f7e310b91c88690f6178fbc9f99e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=80=E6=BA=90=E6=B5=B7=E5=93=A5?= Date: Wed, 28 Jun 2023 13:53:50 +0800 Subject: [PATCH] fixed NPE in ArrayTypeHandler.setNonNullParameter --- .../mybatisflex/core/audit/AuditMessage.java | 20 +-- .../com/mybatisflex/core/util/SqlUtil.java | 14 +- .../java/com/mybatisflex/test/Account05.java | 128 ++++++++++++++++++ ...AccountInsertWithArrayAttrTestStarter.java | 63 +++++++++ .../src/main/resources/data05.sql | 9 ++ .../src/main/resources/schema05.sql | 21 +++ 6 files changed, 243 insertions(+), 12 deletions(-) create mode 100644 mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/Account05.java create mode 100644 mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/AccountInsertWithArrayAttrTestStarter.java create mode 100644 mybatis-flex-test/mybatis-flex-native-test/src/main/resources/data05.sql create mode 100644 mybatis-flex-test/mybatis-flex-native-test/src/main/resources/schema05.sql diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/audit/AuditMessage.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/audit/AuditMessage.java index 098dfaad..d8335e33 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/audit/AuditMessage.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/audit/AuditMessage.java @@ -25,10 +25,7 @@ import java.lang.reflect.Proxy; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * SQL 审计详细消息。 @@ -189,14 +186,17 @@ public class AuditMessage implements Serializable { } private void doAddParam(Statement statement, Object object) { - if (object instanceof TypeHandlerObject) { - try { + try { + if (object instanceof TypeHandlerObject) { ((TypeHandlerObject) object).setParameter(createPreparedStatement(statement), 0); - } catch (SQLException e) { - //ignore + } else if (object instanceof java.sql.Array) { + Object array = ((java.sql.Array) object).getArray(); + queryParams.add(array); + } else { + queryParams.add(object); } - } else { - queryParams.add(object); + } catch (SQLException e) { + //ignore } } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/SqlUtil.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/SqlUtil.java index fedae9d1..120522f9 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/SqlUtil.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/SqlUtil.java @@ -15,8 +15,10 @@ */ package com.mybatisflex.core.util; +import java.lang.reflect.Array; import java.time.LocalDateTime; import java.util.Date; +import java.util.StringJoiner; import java.util.regex.Matcher; public class SqlUtil { @@ -81,7 +83,8 @@ public class SqlUtil { /** * 替换 sql 中的问号 ? - * @param sql sql 内容 + * + * @param sql sql 内容 * @param params 参数 * @return 完整的 sql */ @@ -96,6 +99,14 @@ public class SqlUtil { else if (value instanceof Number || value instanceof Boolean) { sql = sql.replaceFirst("\\?", value.toString()); } + // array + else if (ClassUtil.isArray(value.getClass())) { + StringJoiner joiner = new StringJoiner(","); + for (int i = 0; i < Array.getLength(value); i++) { + joiner.add(String.valueOf(Array.get(value, i))); + } + sql = sql.replaceFirst("\\?", "[" + joiner + "]"); + } // other else { StringBuilder sb = new StringBuilder(); @@ -116,5 +127,4 @@ public class SqlUtil { } - } diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/Account05.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/Account05.java new file mode 100644 index 00000000..c54993dd --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/Account05.java @@ -0,0 +1,128 @@ +package com.mybatisflex.test; + +import com.mybatisflex.annotation.*; +import com.mybatisflex.core.handler.Fastjson2TypeHandler; +import com.mybatisflex.core.mask.Masks; +import org.apache.ibatis.type.ArrayTypeHandler; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Table(value = "tb_account", dataSource = "ds2", onSet = AccountOnSetListener.class) +public class Account05 extends BaseEntity implements Serializable, AgeAware { + + private static final long serialVersionUID = 1L; + + @Id(keyType = KeyType.Auto) + private Long id; + + @ColumnMask(Masks.CHINESE_NAME) + private String userName; + + private int age; + + @NotBlank + private Date birthday; + + @Column(typeHandler = Fastjson2TypeHandler.class, isLarge = true) + private Map options; + + @Column(isLogicDelete = true) + private Boolean isDelete; + + private List
articles; + + @Column(typeHandler = ArrayTypeHandler.class) + private Long[] dataScope; + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + @Override + public int getAge() { + return age; + } + + @Override + public void setAge(int age) { + this.age = age; + } + + public Date getBirthday() { + return birthday; + } + + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + + public Map getOptions() { + return options; + } + + public void setOptions(Map options) { + this.options = options; + } + + public void addOption(String key, Object value) { + if (options == null) { + options = new HashMap<>(); + } + options.put(key, value); + } + + public Boolean getDelete() { + return isDelete; + } + + public void setDelete(Boolean delete) { + isDelete = delete; + } + + public List
getArticles() { + return articles; + } + + public void setArticles(List
articles) { + this.articles = articles; + } + + public Long[] getDataScope() { + return dataScope; + } + + public void setDataScope(Long[] dataScope) { + this.dataScope = dataScope; + } + + @Override + public String toString() { + return "Account{" + + "id=" + id + + ", userName='" + userName + '\'' + + ", age=" + age + + ", birthday=" + birthday + + ", options=" + options + + ", isDelete=" + isDelete + + ", articles=" + articles + + '}'; + } +} diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/AccountInsertWithArrayAttrTestStarter.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/AccountInsertWithArrayAttrTestStarter.java new file mode 100644 index 00000000..c37158af --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/AccountInsertWithArrayAttrTestStarter.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * 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 + *

+ * http://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.mybatisflex.test; + +import com.mybatisflex.core.MybatisFlexBootstrap; +import com.mybatisflex.core.audit.AuditManager; +import com.mybatisflex.core.audit.ConsoleMessageCollector; +import com.mybatisflex.core.audit.MessageCollector; +import com.mybatisflex.mapper.Account05Mapper; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; + +import javax.sql.DataSource; + +public class AccountInsertWithArrayAttrTestStarter { + + public static void main(String[] args) { + DataSource dataSource = new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("schema05.sql") + .addScript("data05.sql") + .build(); + + MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance() + .setDataSource(dataSource) + .addMapper(Account05Mapper.class) + .start(); + + //开启审计功能 + AuditManager.setAuditEnable(true); + + //设置 SQL 审计收集器 + MessageCollector collector = new ConsoleMessageCollector(); + AuditManager.setMessageCollector(collector); +// +// String insertSql = "INSERT INTO `tb_account`(`id`,`user_name`, `age`, `birthday`, `options`, `is_delete`, `data_scope`) VALUES (?, ?, ?, ?, ?, ?, ?)"; +// Db.insertBySql(insertSql,null,"lisi",null,null,null,null,null); + + + Account05Mapper accountMapper = bootstrap.getMapper(Account05Mapper.class); + + Account05 account = new Account05(); + account.setId(3L); + account.setUserName("lisi"); + account.setDataScope(new Long[]{1L,2L}); + + accountMapper.insertWithPk(account,false); + + } +} diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/resources/data05.sql b/mybatis-flex-test/mybatis-flex-native-test/src/main/resources/data05.sql new file mode 100644 index 00000000..3d616cad --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/resources/data05.sql @@ -0,0 +1,9 @@ +INSERT INTO tb_account +VALUES (1, '张三', 18, 0,'2020-01-11', null,null,0), + (2, '王麻子叔叔', 19, 1, '2021-03-21', null,null,0); + + +INSERT INTO tb_article +VALUES (1, 1,'标题1', '内容1',0), + (2, 2,'标题2', '内容2',0), + (3, 1,'标题3', '内容3',0); diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/resources/schema05.sql b/mybatis-flex-test/mybatis-flex-native-test/src/main/resources/schema05.sql new file mode 100644 index 00000000..2c75d1a7 --- /dev/null +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/resources/schema05.sql @@ -0,0 +1,21 @@ +CREATE TABLE IF NOT EXISTS `tb_account` +( + `id` INTEGER PRIMARY KEY auto_increment, + `user_name` VARCHAR(100), + `age` Integer, + `sex` Integer, + `birthday` DATETIME, + `options` VARCHAR(1024), + `data_scope` VARCHAR(1024), + `is_delete` Integer +); + + +CREATE TABLE IF NOT EXISTS `tb_article` +( + `id` INTEGER PRIMARY KEY auto_increment, + `account_id` Integer, + `title` VARCHAR(100), + `content` text, + `is_delete` Integer +); \ No newline at end of file