refactor!: 将工厂方法异常类型从 SQLException 改为 IllegalStateException

DefaultBeanRowMapper.of() 及 RowMapper.beanRowMapper() 在反射异常时
不再抛出受检异常 SQLException,改为抛出非受检异常 IllegalStateException。
同时优化相关 Javadoc 文档并同步更新测试断言。

BREAKING CHANGE: beanRowMapper() 和 of() 方法不再抛出 SQLException。
调用方 catch (SQLException e) 将静默失效,建议移除相关 catch 块或
改为 catch (IllegalStateException)。
This commit is contained in:
2026-06-18 02:41:10 +08:00
parent 5100fa5f1d
commit 6f2882cd08
4 changed files with 30 additions and 18 deletions

View File

@@ -1,5 +1,17 @@
# Changelog
## [1.1.0] - Unreleased
### ⚠️ 破坏性变更
- **`DefaultBeanRowMapper.of()` 不再抛出 `SQLException`**:工厂方法在反射异常时改为抛出非受检异常 `IllegalStateException`。调用方如果 `catch (SQLException e)` 包裹 `of()` 调用,该捕获将失效,需移除相关 `catch` 块或改为捕获 `IllegalStateException`
### 文档
- 优化 `DefaultBeanRowMapper` 类注释,明确性能限制和使用建议
---
## [1.0.0] - 2026-06-17
### 重构

View File

@@ -41,16 +41,17 @@ import xyz.zhouxy.jdbc.util.NamingTools;
*
* <p>
* 将 {@link ResultSet} 转换为 Java Bean 的 {@link RowMapper} 的基础实现。
* <i>仅在对性能不敏感的场景下使用。</i>
* <p>
* <i>性能和规则上的限制都比较大,仅在对性能不敏感的场景下便捷使用,
* 一般情况下你应该自定义 {@link RowMapper}。</i>
*
* <p>
* 说明:
* <ul>
* <li>使用反射获取类型信息,也是使用反射调用无参构造器和 {@code setter} 方法。</li>
* <li>{@code propertyColMap} 未指定的列名和属性名的映射时,默认 JavaBean 的属性名为小驼峰,列名为小写蛇形命名。</li>
* <li>支持自定义列名和属性名的映射,当未指定 {@code propertyColMap} 时,默认 JavaBean 的属性名为小驼峰,列名为小写蛇形命名。</li>
* <li>使用 {@link ResultSet#getObject(String, Class)} 从 {@link ResultSet} 中获取属性值。</li>
* <li>JavaBean 属性仅支持引用类型,不支持基本数据类型。</li>
* <li><b>实际使用中更建议针对目标类型自定义 {@link RowMapper}。</b></li>
* </ul>
*
* @author ZhouXY
@@ -86,9 +87,9 @@ public class DefaultBeanRowMapper<T> implements RowMapper<T> {
* @param <T> Bean 类型
* @param beanType Bean 类型
* @return DefaultBeanRowMapper 对象
* @throws SQLException 创建 {@code DefaultBeanRowMapper} 出现错误的异常时抛出
* @throws IllegalStateException 创建 {@code DefaultBeanRowMapper} 出现错误的异常时抛出
*/
public static <T> DefaultBeanRowMapper<T> of(Class<T> beanType) throws SQLException {
public static <T> DefaultBeanRowMapper<T> of(Class<T> beanType) {
return of(beanType, null);
}
@@ -99,10 +100,10 @@ public class DefaultBeanRowMapper<T> implements RowMapper<T> {
* @param beanType Bean 类型
* @param propertyColMap Bean 字段与列名的映射关系。key 是字段value 是列名。
* @return {@code DefaultBeanRowMapper} 对象
* @throws SQLException 创建 {@code DefaultBeanRowMapper} 出现错误的异常时抛出
* @throws IllegalStateException 创建 {@code DefaultBeanRowMapper} 出现错误的异常时抛出
*/
public static <T> DefaultBeanRowMapper<T> of(Class<T> beanType, @Nullable Map<String, String> propertyColMap)
throws SQLException {
public static <T> DefaultBeanRowMapper<T> of(Class<T> beanType,
@Nullable Map<String, String> propertyColMap) {
try {
// 获取无参构造器
Constructor<T> constructor = beanType.getDeclaredConstructor();
@@ -113,10 +114,10 @@ public class DefaultBeanRowMapper<T> implements RowMapper<T> {
return new DefaultBeanRowMapper<>(beanType, constructor, colPropertyMap, colSetterMap);
}
catch (IntrospectionException e) {
throw new SQLException("There is an exception occurs during introspection.", e);
throw new IllegalStateException("There is an exception occurs during introspection.", e);
}
catch (NoSuchMethodException e) {
throw new SQLException("Could not find a no-args constructor in " + beanType.getName(), e);
throw new IllegalStateException("Could not find a no-args constructor in " + beanType.getName(), e);
}
}
@@ -141,7 +142,7 @@ public class DefaultBeanRowMapper<T> implements RowMapper<T> {
return newInstance;
}
catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
throw new SQLException("Could not map row to " + beanType.getName(), e);
throw new IllegalStateException("Could not map row to " + beanType.getName(), e);
}
}

View File

@@ -60,9 +60,9 @@ public interface RowMapper<T> {
* @param <T> Java Bean 的类型
*
* @return {@link DefaultBeanRowMapper}
* @throws SQLException 如果创建 {@link DefaultBeanRowMapper} 失败
* @throws IllegalStateException 如果创建 {@link DefaultBeanRowMapper} 失败
*/
static <T> RowMapper<T> beanRowMapper(Class<T> beanType) throws SQLException {
static <T> RowMapper<T> beanRowMapper(Class<T> beanType) {
return DefaultBeanRowMapper.of(beanType);
}
@@ -74,10 +74,9 @@ public interface RowMapper<T> {
* @param <T> Java Bean 的类型
*
* @return {@link DefaultBeanRowMapper}
* @throws SQLException 如果创建 {@link DefaultBeanRowMapper} 失败
* @throws IllegalStateException 如果创建 {@link DefaultBeanRowMapper} 失败
*/
static <T> RowMapper<T> beanRowMapper(Class<T> beanType, Map<String, String> propertyColMap)
throws SQLException {
static <T> RowMapper<T> beanRowMapper(Class<T> beanType, Map<String, String> propertyColMap) {
return DefaultBeanRowMapper.of(beanType, propertyColMap);
}
}

View File

@@ -137,9 +137,9 @@ class RowMapperTest extends BaseH2Test {
}
@Test
@DisplayName("DefaultBeanRowMapper无无参构造器的 Bean 抛出 SQLException")
@DisplayName("DefaultBeanRowMapper无无参构造器的 Bean 抛出 IllegalStateException")
void testDefaultBeanRowMapperNoNoArgConstructor() {
assertThrows(SQLException.class, () ->
assertThrows(IllegalStateException.class, () ->
DefaultBeanRowMapper.of(BeanWithoutNoArgConstructor.class));
}