mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
修复Druid连接池无法设置部分属性问题
This commit is contained in:
commit
f0105a2121
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
### 🐣新特性
|
### 🐣新特性
|
||||||
* 【core 】 WatchServer新增通过Path获取WatchKey方法(pr#1145@Gitee)
|
* 【core 】 WatchServer新增通过Path获取WatchKey方法(pr#1145@Gitee)
|
||||||
|
* 【core 】 CopyOptions中增加setAutoTransCamelCase方法(issue#3452@Github)
|
||||||
|
|
||||||
### 🐞Bug修复
|
### 🐞Bug修复
|
||||||
* 【core 】 修复StrJoin当append内容后调用length()会出现空指针问题(issue#3444@Github)
|
* 【core 】 修复StrJoin当append内容后调用length()会出现空指针问题(issue#3444@Github)
|
||||||
|
@ -408,7 +408,9 @@ public class BeanUtil {
|
|||||||
* @param isToCamelCase 是否将Map中的下划线风格key转换为驼峰风格
|
* @param isToCamelCase 是否将Map中的下划线风格key转换为驼峰风格
|
||||||
* @param copyOptions 转Bean选项
|
* @param copyOptions 转Bean选项
|
||||||
* @return Bean
|
* @return Bean
|
||||||
|
* @deprecated isToCamelCase参数无效,请使用 {@link #toBean(Object, Class, CopyOptions)}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static <T> T mapToBean(Map<?, ?> map, Class<T> beanClass, boolean isToCamelCase, CopyOptions copyOptions) {
|
public static <T> T mapToBean(Map<?, ?> map, Class<T> beanClass, boolean isToCamelCase, CopyOptions copyOptions) {
|
||||||
return fillBeanWithMap(map, ReflectUtil.newInstanceIfPossible(beanClass), isToCamelCase, copyOptions);
|
return fillBeanWithMap(map, ReflectUtil.newInstanceIfPossible(beanClass), isToCamelCase, copyOptions);
|
||||||
}
|
}
|
||||||
@ -437,7 +439,9 @@ public class BeanUtil {
|
|||||||
* @param isToCamelCase 是否将下划线模式转换为驼峰模式
|
* @param isToCamelCase 是否将下划线模式转换为驼峰模式
|
||||||
* @param isIgnoreError 是否忽略注入错误
|
* @param isIgnoreError 是否忽略注入错误
|
||||||
* @return Bean
|
* @return Bean
|
||||||
|
* @deprecated isToCamelCase参数无效,请使用{@link #fillBeanWithMap(Map, Object, boolean)}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static <T> T fillBeanWithMap(Map<?, ?> map, T bean, boolean isToCamelCase, boolean isIgnoreError) {
|
public static <T> T fillBeanWithMap(Map<?, ?> map, T bean, boolean isToCamelCase, boolean isIgnoreError) {
|
||||||
return fillBeanWithMap(map, bean, isToCamelCase, CopyOptions.create().setIgnoreError(isIgnoreError));
|
return fillBeanWithMap(map, bean, isToCamelCase, CopyOptions.create().setIgnoreError(isIgnoreError));
|
||||||
}
|
}
|
||||||
@ -465,7 +469,11 @@ public class BeanUtil {
|
|||||||
* @return Bean
|
* @return Bean
|
||||||
*/
|
*/
|
||||||
public static <T> T fillBeanWithMap(Map<?, ?> map, T bean, CopyOptions copyOptions) {
|
public static <T> T fillBeanWithMap(Map<?, ?> map, T bean, CopyOptions copyOptions) {
|
||||||
return fillBeanWithMap(map, bean, false, copyOptions);
|
if (MapUtil.isEmpty(map)) {
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
copyProperties(map, bean, copyOptions);
|
||||||
|
return bean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -478,14 +486,18 @@ public class BeanUtil {
|
|||||||
* @param copyOptions 属性复制选项 {@link CopyOptions}
|
* @param copyOptions 属性复制选项 {@link CopyOptions}
|
||||||
* @return Bean
|
* @return Bean
|
||||||
* @since 3.3.1
|
* @since 3.3.1
|
||||||
|
* @deprecated isToCamelCase参数无效,请使用{@link #fillBeanWithMap(Map, Object, CopyOptions)}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static <T> T fillBeanWithMap(Map<?, ?> map, T bean, boolean isToCamelCase, CopyOptions copyOptions) {
|
public static <T> T fillBeanWithMap(Map<?, ?> map, T bean, boolean isToCamelCase, CopyOptions copyOptions) {
|
||||||
if (MapUtil.isEmpty(map)) {
|
if (MapUtil.isEmpty(map)) {
|
||||||
return bean;
|
return bean;
|
||||||
}
|
}
|
||||||
if (isToCamelCase) {
|
|
||||||
map = MapUtil.toCamelCaseMap(map);
|
// issue#3452,参数无效,MapToBeanCopier中已经有转驼峰逻辑
|
||||||
}
|
// if (isToCamelCase) {
|
||||||
|
// map = MapUtil.toCamelCaseMap(map);
|
||||||
|
// }
|
||||||
copyProperties(map, bean, copyOptions);
|
copyProperties(map, bean, copyOptions);
|
||||||
return bean;
|
return bean;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ public class BeanToBeanCopier<S, T> extends AbsCopier<S, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查目标字段可写性
|
// 检查目标字段可写性
|
||||||
final PropDesc tDesc = targetPropDescMap.get(sFieldName);
|
final PropDesc tDesc = this.copyOptions.findPropDesc(targetPropDescMap, sFieldName);
|
||||||
if (null == tDesc || false == tDesc.isWritable(this.copyOptions.transientSupport)) {
|
if (null == tDesc || false == tDesc.isWritable(this.copyOptions.transientSupport)) {
|
||||||
// 字段不可写,跳过之
|
// 字段不可写,跳过之
|
||||||
return;
|
return;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cn.hutool.core.bean.copier;
|
package cn.hutool.core.bean.copier;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.PropDesc;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.convert.TypeConverter;
|
import cn.hutool.core.convert.TypeConverter;
|
||||||
@ -70,6 +71,11 @@ public class CopyOptions implements Serializable {
|
|||||||
*/
|
*/
|
||||||
protected boolean override = true;
|
protected boolean override = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否自动转换为驼峰方式
|
||||||
|
*/
|
||||||
|
protected boolean autoTransCamelCase = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 源对象和目标对象都是 {@code Map} 时, 需要忽略的源对象 {@code Map} key
|
* 源对象和目标对象都是 {@code Map} 时, 需要忽略的源对象 {@code Map} key
|
||||||
*/
|
*/
|
||||||
@ -321,6 +327,19 @@ public class CopyOptions implements Serializable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置是否自动转换为驼峰方式<br>
|
||||||
|
* 一般用于map转bean和bean转bean出现非驼峰格式时,在尝试转换失败的情况下,是否二次检查转为驼峰匹配
|
||||||
|
*
|
||||||
|
* @param autoTransCamelCase 是否自动转换为驼峰方式
|
||||||
|
* @return this
|
||||||
|
* @since 5.8.25
|
||||||
|
*/
|
||||||
|
public CopyOptions setAutoTransCamelCase(final boolean autoTransCamelCase) {
|
||||||
|
this.autoTransCamelCase = autoTransCamelCase;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置自定义类型转换器,默认使用全局万能转换器转换。
|
* 设置自定义类型转换器,默认使用全局万能转换器转换。
|
||||||
*
|
*
|
||||||
@ -391,4 +410,25 @@ public class CopyOptions implements Serializable {
|
|||||||
|
|
||||||
return false == this.ignoreKeySet.contains(key);
|
return false == this.ignoreKeySet.contains(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找Map对应Bean的名称<br>
|
||||||
|
* 尝试原名称、转驼峰名称、isXxx去掉is的名称
|
||||||
|
*
|
||||||
|
* @param targetPropDescMap 目标bean的属性描述Map
|
||||||
|
* @param sKeyStr 键或字段名
|
||||||
|
* @return {@link PropDesc}
|
||||||
|
*/
|
||||||
|
protected PropDesc findPropDesc(final Map<String, PropDesc> targetPropDescMap, final String sKeyStr) {
|
||||||
|
PropDesc propDesc = targetPropDescMap.get(sKeyStr);
|
||||||
|
// 转驼峰尝试查找
|
||||||
|
if (null == propDesc && this.autoTransCamelCase) {
|
||||||
|
final String camelCaseKey = StrUtil.toCamelCase(sKeyStr);
|
||||||
|
if (!StrUtil.equals(sKeyStr, camelCaseKey)) {
|
||||||
|
// 只有转换为驼峰后与原key不同才重复查询,相同说明本身就是驼峰,不需要二次查询
|
||||||
|
propDesc = targetPropDescMap.get(camelCaseKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return propDesc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ public class MapToBeanCopier<T> extends AbsCopier<Map<?, ?>, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查目标字段可写性
|
// 检查目标字段可写性
|
||||||
final PropDesc tDesc = findPropDesc(targetPropDescMap, sKeyStr);
|
final PropDesc tDesc = this.copyOptions.findPropDesc(targetPropDescMap, sKeyStr);
|
||||||
if (null == tDesc || false == tDesc.isWritable(this.copyOptions.transientSupport)) {
|
if (null == tDesc || false == tDesc.isWritable(this.copyOptions.transientSupport)) {
|
||||||
// 字段不可写,跳过之
|
// 字段不可写,跳过之
|
||||||
return;
|
return;
|
||||||
@ -96,24 +96,4 @@ public class MapToBeanCopier<T> extends AbsCopier<Map<?, ?>, T> {
|
|||||||
});
|
});
|
||||||
return this.target;
|
return this.target;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 查找Map对应Bean的名称<br>
|
|
||||||
* 尝试原名称、转驼峰名称、isXxx去掉is的名称
|
|
||||||
*
|
|
||||||
* @param targetPropDescMap 目标bean的属性描述Map
|
|
||||||
* @param sKeyStr 键或字段名
|
|
||||||
* @return {@link PropDesc}
|
|
||||||
*/
|
|
||||||
private PropDesc findPropDesc(Map<String, PropDesc> targetPropDescMap, String sKeyStr){
|
|
||||||
PropDesc propDesc = targetPropDescMap.get(sKeyStr);
|
|
||||||
if(null != propDesc){
|
|
||||||
return propDesc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转驼峰尝试查找
|
|
||||||
sKeyStr = StrUtil.toCamelCase(sKeyStr);
|
|
||||||
propDesc = targetPropDescMap.get(sKeyStr);
|
|
||||||
return propDesc;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package cn.hutool.core.bean;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.copier.CopyOptions;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class Issue3452Test {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fillBeanWithMapTest() {
|
||||||
|
final Map<String, Object> properties = new HashMap<>();
|
||||||
|
properties.put("name", "JohnDoe");
|
||||||
|
properties.put("user_age", 25);
|
||||||
|
final User user = BeanUtil.fillBeanWithMap(
|
||||||
|
properties, new User(), CopyOptions.create());
|
||||||
|
Assert.assertEquals("JohnDoe", user.getName());
|
||||||
|
Assert.assertEquals(25, user.getUserAge());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static class User {
|
||||||
|
private String name;
|
||||||
|
private int userAge;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user