补充文档注释

pull/1/head
ZhouXY108 2024-11-02 10:55:23 +08:00
parent bd08be5928
commit 6b5bcf0b5c
6 changed files with 718 additions and 71 deletions

View File

@ -16,49 +16,78 @@
package xyz.zhouxy.jdbc; package xyz.zhouxy.jdbc;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;
import javax.annotation.Nonnull;
import com.google.common.annotations.Beta; import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
import xyz.zhouxy.plusone.commons.collection.AbstractMapWrapper; import xyz.zhouxy.plusone.commons.collection.AbstractMapWrapper;
import xyz.zhouxy.plusone.commons.util.AssertTools;
import xyz.zhouxy.plusone.commons.util.OptionalTools; import xyz.zhouxy.plusone.commons.util.OptionalTools;
import xyz.zhouxy.plusone.commons.util.StringTools; import xyz.zhouxy.plusone.commons.util.StringTools;
import java.util.*; /**
* DbRecord
*
* <p>
* Map<String, Object> DB
* </p>
*
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108">ZhouXY</a>
* @since 1.0.0
*/
@Beta @Beta
public class DbRecord extends AbstractMapWrapper<String, Object, DbRecord> { public class DbRecord extends AbstractMapWrapper<String, Object, DbRecord> {
public DbRecord() { public DbRecord() {
super(new HashMap<>(), k -> Preconditions.checkArgument(StringTools.isNotBlank(k), "Key must has text."), null); super(new HashMap<>(),
k -> AssertTools.checkArgument(StringTools.isNotBlank(k), "Key must has text."),
null);
} }
public DbRecord(Map<String, Object> map) { public DbRecord(Map<String, Object> map) {
super(map, k -> Preconditions.checkArgument(StringTools.isNotBlank(k), "Key must has text."), null); super(map,
k -> AssertTools.checkArgument(StringTools.isNotBlank(k), "Key must has text."),
null);
} }
/**
* {@link String} {@link Optional}
* {@code key} {@link Optional#empty()}
*/
public Optional<String> getValueAsString(String key) { public Optional<String> getValueAsString(String key) {
return this.getAndConvert(key); return this.getAndConvert(key);
} }
public <T> List<T> getValueAsList(String key) { /**
return this.<Collection<T>>getAndConvert(key) * {@code int} {@link OptionalInt}
.map(l -> (l instanceof List) ? (List<T>) l : new ArrayList<>(l)) * {@code key} {@link OptionalInt#empty()}
.orElse(Collections.emptyList()); */
} @Nonnull
public <T> Set<T> getValueAsSet(String key) {
return this.<Collection<T>>getAndConvert(key)
.map(l -> (l instanceof Set) ? (Set<T>) l : new HashSet<>(l))
.orElse(Collections.emptySet());
}
public OptionalInt getValueAsInt(String key) { public OptionalInt getValueAsInt(String key) {
return OptionalTools.toOptionalInt(this.getAndConvert(key)); return OptionalTools.toOptionalInt(this.getAndConvert(key));
} }
/**
* {@code long} {@link OptionalLong}
* {@code key} {@link OptionalLong#empty()}
*/
@Nonnull
public OptionalLong getValueAsLong(String key) { public OptionalLong getValueAsLong(String key) {
return OptionalTools.toOptionalLong(this.getAndConvert(key)); return OptionalTools.toOptionalLong(this.getAndConvert(key));
} }
/**
* {@code double} {@link OptionalDouble}
* {@code key} {@link OptionalDouble#empty()}
*/
@Nonnull
public OptionalDouble getValueAsDouble(String key) { public OptionalDouble getValueAsDouble(String key) {
return OptionalTools.toOptionalDouble(this.getAndConvert(key)); return OptionalTools.toOptionalDouble(this.getAndConvert(key));
} }

View File

@ -35,9 +35,28 @@ import javax.annotation.Nullable;
import com.google.common.base.CaseFormat; import com.google.common.base.CaseFormat;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
/**
* DefaultBeanRowMapper
*
* <p>
* {@link ResultSet} Java Bean {@link RowMapper}
* </p>
*
* <p>
* <b>NOTE: 使使 {@code setter}
* 使 {@link RowMapper}</b>
* </p>
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108">ZhouXY</a>
* @since 1.0.0
*/
public class DefaultBeanRowMapper<T> implements RowMapper<T> { public class DefaultBeanRowMapper<T> implements RowMapper<T> {
/** Bean 的无参构造器 */
private final Constructor<T> constructor; private final Constructor<T> constructor;
/** 列名到属性的映射 */
private final Map<String, PropertyDescriptor> colPropertyMap; private final Map<String, PropertyDescriptor> colPropertyMap;
private DefaultBeanRowMapper(Constructor<T> constructor, Map<String, PropertyDescriptor> colPropertyMap) { private DefaultBeanRowMapper(Constructor<T> constructor, Map<String, PropertyDescriptor> colPropertyMap) {
@ -45,10 +64,29 @@ public class DefaultBeanRowMapper<T> implements RowMapper<T> {
this.colPropertyMap = colPropertyMap; this.colPropertyMap = colPropertyMap;
} }
/**
* DefaultBeanRowMapper
*
* @param <T> Bean
* @param beanType Bean
* @return DefaultBeanRowMapper
* @throws SQLException DefaultBeanRowMapper
*/
@StaticFactoryMethod(DefaultBeanRowMapper.class)
public static <T> DefaultBeanRowMapper<T> of(Class<T> beanType) throws SQLException { public static <T> DefaultBeanRowMapper<T> of(Class<T> beanType) throws SQLException {
return of(beanType, null); return of(beanType, null);
} }
/**
* DefaultBeanRowMapper
*
* @param <T> Bean
* @param beanType Bean
* @param propertyColMap Bean key value
* @return DefaultBeanRowMapper
* @throws SQLException DefaultBeanRowMapper
*/
@StaticFactoryMethod(DefaultBeanRowMapper.class)
public static <T> DefaultBeanRowMapper<T> of(Class<T> beanType, @Nullable Map<String, String> propertyColMap) public static <T> DefaultBeanRowMapper<T> of(Class<T> beanType, @Nullable Map<String, String> propertyColMap)
throws SQLException { throws SQLException {
try { try {
@ -60,6 +98,7 @@ public class DefaultBeanRowMapper<T> implements RowMapper<T> {
BeanInfo beanInfo = Introspector.getBeanInfo(beanType); BeanInfo beanInfo = Introspector.getBeanInfo(beanType);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
// Bean 的属性名为小驼峰,对应的列名为下划线
Function<? super PropertyDescriptor, String> keyMapper; Function<? super PropertyDescriptor, String> keyMapper;
if (propertyColMap == null || propertyColMap.isEmpty()) { if (propertyColMap == null || propertyColMap.isEmpty()) {
keyMapper = p -> CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, p.getName()); keyMapper = p -> CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, p.getName());
@ -84,13 +123,17 @@ public class DefaultBeanRowMapper<T> implements RowMapper<T> {
} }
} }
/** {@inheritDoc} */
@Override @Override
public T mapRow(ResultSet rs, int rowNumber) throws SQLException { public T mapRow(ResultSet rs, int rowNumber) throws SQLException {
try { try {
// 调用无参构造器创建实例
T newInstance = this.constructor.newInstance(); T newInstance = this.constructor.newInstance();
ResultSetMetaData metaData = rs.getMetaData(); ResultSetMetaData metaData = rs.getMetaData();
// 遍历结果的每一列
for (int i = 1; i <= metaData.getColumnCount(); i++) { for (int i = 1; i <= metaData.getColumnCount(); i++) {
String colName = metaData.getColumnName(i); String colName = metaData.getColumnName(i);
// 获取查询结果列名对应的属性,调用 setter
PropertyDescriptor propertyDescriptor = this.colPropertyMap.get(colName); PropertyDescriptor propertyDescriptor = this.colPropertyMap.get(colName);
if (propertyDescriptor != null) { if (propertyDescriptor != null) {
Method setter = propertyDescriptor.getWriteMethod(); Method setter = propertyDescriptor.getWriteMethod();

View File

@ -27,12 +27,21 @@ import java.util.OptionalLong;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.google.common.base.Preconditions;
import xyz.zhouxy.plusone.commons.collection.CollectionTools; import xyz.zhouxy.plusone.commons.collection.CollectionTools;
import xyz.zhouxy.plusone.commons.util.ArrayTools; import xyz.zhouxy.plusone.commons.util.ArrayTools;
import xyz.zhouxy.plusone.commons.util.AssertTools;
import xyz.zhouxy.plusone.commons.util.OptionalTools; import xyz.zhouxy.plusone.commons.util.OptionalTools;
/**
* ParamBuilder
*
* <p>
* JDBC {@code Object[]} {@link PreparedStatement}
* </p>
*
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108">ZhouXY</a>
* @since 1.0.0
*/
public class ParamBuilder { public class ParamBuilder {
public static final Object[] EMPTY_OBJECT_ARRAY = {}; public static final Object[] EMPTY_OBJECT_ARRAY = {};
@ -60,8 +69,8 @@ public class ParamBuilder {
} }
public static <T> List<Object[]> buildBatchParams(final Collection<T> c, final Function<T, Object[]> func) { public static <T> List<Object[]> buildBatchParams(final Collection<T> c, final Function<T, Object[]> func) {
Preconditions.checkNotNull(c, "The collection can not be null."); AssertTools.checkNotNull(c, "The collection can not be null.");
Preconditions.checkNotNull(func, "The func can not be null."); AssertTools.checkNotNull(func, "The func can not be null.");
if (CollectionTools.isEmpty(c)) { if (CollectionTools.isEmpty(c)) {
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -19,7 +19,21 @@ package xyz.zhouxy.jdbc;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
/**
* ResultHandler
*
* <p>
* {@link ResultSet}
* </p>
*
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108">ZhouXY</a>
* @since 1.0.0
*/
@FunctionalInterface @FunctionalInterface
public interface ResultHandler<T> { public interface ResultHandler<T> {
/**
* {@link ResultSet}
*/
T handle(ResultSet resultSet) throws SQLException; T handle(ResultSet resultSet) throws SQLException;
} }

View File

@ -22,10 +22,21 @@ import java.sql.SQLException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
/**
* RowMapper
*
* <p>
* {@link ResultSet}
* </p>
*
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108">ZhouXY</a>
* @since 1.0.0
*/
@FunctionalInterface @FunctionalInterface
public interface RowMapper<T> { public interface RowMapper<T> {
T mapRow(ResultSet rs, int rowNumber) throws SQLException; T mapRow(ResultSet rs, int rowNumber) throws SQLException;
/** 每一行数据转换为 {@link HashMap} */
public static final RowMapper<Map<String, Object>> HASH_MAP_MAPPER = (rs, rowNumber) -> { public static final RowMapper<Map<String, Object>> HASH_MAP_MAPPER = (rs, rowNumber) -> {
Map<String, Object> result = new HashMap<>(); Map<String, Object> result = new HashMap<>();
ResultSetMetaData metaData = rs.getMetaData(); ResultSetMetaData metaData = rs.getMetaData();
@ -37,13 +48,16 @@ public interface RowMapper<T> {
return result; return result;
}; };
/** 每一行数据转换为 {@link DbRecord} */
public static final RowMapper<DbRecord> RECORD_MAPPER = public static final RowMapper<DbRecord> RECORD_MAPPER =
(rs, rowNumber) -> new DbRecord(HASH_MAP_MAPPER.mapRow(rs, rowNumber)); (rs, rowNumber) -> new DbRecord(HASH_MAP_MAPPER.mapRow(rs, rowNumber));
/** 默认实现的将 {@link ResultSet} 转换为 Java Bean 的 {@link RowMapper}。 */
public static <T> RowMapper<T> beanRowMapper(Class<T> beanType) throws SQLException { public static <T> RowMapper<T> beanRowMapper(Class<T> beanType) throws SQLException {
return DefaultBeanRowMapper.of(beanType); return DefaultBeanRowMapper.of(beanType);
} }
/** 默认实现的将 {@link ResultSet} 转换为 Java Bean 的 {@link RowMapper}。 */
public static <T> RowMapper<T> beanRowMapper(Class<T> beanType, Map<String, String> propertyColMap) public static <T> RowMapper<T> beanRowMapper(Class<T> beanType, Map<String, String> propertyColMap)
throws SQLException { throws SQLException {
return DefaultBeanRowMapper.of(beanType, propertyColMap); return DefaultBeanRowMapper.of(beanType, propertyColMap);

File diff suppressed because it is too large Load Diff