jdbc实现类mybatis结果集解析

Jdbc 比较繁琐的一个操作就是解析结果集ResultSet, 在实际开发时, 通常会将对结果集的解析封装为一个工具类. 需要注意的时, jdbc查询出来的属性可能不能直接转换为java的类型, 比如说java.sql.Date, 不能直接转换为java.util.Date 或LocalDate等类型, 需要自定义转换器. 如果比较熟悉Mybatis的话, 会发现Mybatis底层也封装了大量的类型转换器.

1. 工具类源码

笔者的工具类比较简单, 只封装了三个方法:

方法签名 方法描述 参数说明

public static LinkedHashMap<String, Object> toPropertyMap(ResultSet resultSet) throws SQLException 转换单行结果集为Map结构. key为列别名, value为列值 resultSet: 查询结果集

public static T toBean(ResultSet resultSet, Class clz) 转换结果集为单行对象 clz: 目标对象类型

resultSet: 结果集

public static List toBeans(ResultSet resultSet, Class clz) throws SQLException 转换结果集为java对象集合. clz: 要转换的javaBean类

resultSet: 结果集

1.1 ResultSetUtil 源码

/** 结果集解析工具类

* @since 1.0

* @author zongf

* @created 2019-07-18

*/

public class ResultSetUtil {

    /** 转换单行结果集为Map结构. key为列别名, value为列值

    * @param resultSet 查询结果集

    * @return 结果集中为空时, 返回null

    * @since 1.0

    * @author zongf

    * @created 2019-07-18

    */

    public static LinkedHashMap<String, Object> toPropertyMap(ResultSet resultSet) throws SQLException {

        // 如果结果集为空,则返回null

        if (!resultSet.next()) return null;

        LinkedHashMap<String, Object> cloumnMap = new LinkedHashMap<>();

        // 获取结果集元信息

        ResultSetMetaData metaData = resultSet.getMetaData();

        // 获取每一列列名与值

        for (int i = 1; i <= metaData.getColumnCount(); i++) {

            // 获取列别名为key

            String columnLabel = metaData.getColumnLabel(i);

            Object columnValue = resultSet.getObject(i);

            cloumnMap.put(columnLabel, columnValue);

        }

        return cloumnMap;

    }

    /** 转换结果集为单行对象

    * @param clz      目标对象类型

    * @param resultSet 结果集

    * @since 1.0

    * @return null

    * @author zongf

    * @created 2019-07-18

    */

    public static <T> T toBean(ResultSet resultSet, Class<T> clz) {

        try {

            LinkedHashMap<String, Object> propertyMap = toPropertyMap(resultSet);

            return ReflectUtil.newInstance(clz, propertyMap, new DateTypeConverter());

        } catch (SQLException e) {

            throw new RuntimeException("sql 执行异常!", e);

        }

    }

    /** 转换结果集为java对象集合.

    * @param clz      要转换的javaBean类

    * @param resultSet 结果集

    * @return 结果集中没有数据时, 返回null

    * @since 1.0

    * @author zongf

    * @created 2019-07-18

    */

    public static <T> List<T> toBeans(ResultSet resultSet, Class<T> clz) throws SQLException {

        List<T> list = new ArrayList<>();

        LinkedHashMap<String, Object> propertyMap = null;

        // 解析结果集

        while ((propertyMap = toPropertyMap(resultSet)) != null) {

            T t = (T) ReflectUtil.newInstance(clz, propertyMap, new DateTypeConverter());

            if(t != null) list.add(t);

        }

        return list.size() > 0 ? list : null;

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

1.2 ReflectUtil 源码

这是笔者对使用到的反射技术封装的一个简单工具类.

/** 反射工具类

* @since 1.0

* @author zongf

* @created 2019-07-18

*/

public class ReflectUtil {

    /**为对象属性赋值

    * @param target 目标对象

    * @param property 属性名

    * @param property 属性名

    * @return value 属性值

    * @since 1.0

    * @author zongf

    * @created 2019-07-18

    */

    public static void setPropertyValue(Object target, String property, Object value) {

        try {

            PropertyDescriptor descriptor = new PropertyDescriptor(property, target.getClass());

            Method writeMethod = descriptor.getWriteMethod();

            writeMethod.invoke(target, value);

        } catch (Exception e) {

            throw new RuntimeException("为对象属性赋值异常!",e);

        }

    }

    /** 获取对象属性值

    * @param target 目标对象

    * @param property 属性

    * @return Object 返回对象属性值

    * @since 1.0

    * @author zongf

    * @created 2019-07-18

    */

    public static Object getPropertyValue(Object target, String property) {

        try {

            PropertyDescriptor descriptor = new PropertyDescriptor(property, target.getClass());

            Method readMethod = descriptor.getReadMethod();

            return readMethod.invoke(target);

        } catch (Exception e) {

            throw new RuntimeException("获取对象属性异常!",e);

        }

    }

    /** 反射创建对象

    * @param clz 目标对象的类型

    * @return propertiesMap 目标对象的属性与值

    * @since 1.0

    * @author zongf

    * @created 2019-07-18

    */

    public static <T> T newInstance(Class<T> clz, HashMap<String, Object> propertiesMap, DateTypeConverter typeConverter){

        // 如果属性为空, 则不进行创建, 返回null

        if (propertiesMap == null || propertiesMap.isEmpty()) {

            return null;

        }

        // 使用无参数构造方法创建对象

        T t = null;

        try {

            t = clz.newInstance();

            for (Map.Entry<String, Object> entry : propertiesMap.entrySet()) {

                // 获取对象属性与值

                String property = entry.getKey();

                Object value = entry.getValue();

                // 获取属性描述符

                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(property, clz);

                // 获取属性类型

                Class<?> propertyType = propertyDescriptor.getPropertyType();

                // 使用类型转换器转换参数类型

                value = typeConverter.convert(value, propertyType);

                // 调用set方法, 赋值

                Method writeMethod = propertyDescriptor.getWriteMethod();

                writeMethod.invoke(t, value);

            }

        } catch (Exception e) {

            throw new RuntimeException("反射创建对象失败!", e);

        }

        return t;

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

1.3 DateTypeConverter 转换器

笔者仅仅编写了一个日期类型的转换器, 在企业开发中, 可能需要用到的转换器会更多.

/** 日期类型转换器

* @since 1.0

* @author zongf

* @created 2019-07-18

*/

public class DateTypeConverter {

    /** 转换对象的类型

    * @param value 值

    * @param javaType java类型

    * @return 转换后的类型

    * @since 1.0

    * @author zongf

    * @created 2019-07-18

    */

    public Object convert(Object value, Class javaType) {

        Object obj = value;

        // 如果是java 日期

        if(javaType.equals(Date.class)) {

            java.sql.Date date = (java.sql.Date) value;

            obj = date.toInstant().getEpochSecond();

            // 如果是java8 日期

        } else if(javaType.equals(LocalDate.class)){

            obj = ((java.sql.Date) value).toLocalDate();

        } else {

            obj = value;

        }

        return obj;

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

2. 单元测试

2.1 创建javaBean

测试时, 需要创建t_user表和javabean, 笔者这边仅给出javabean的定义.

public class UserPO {

    private Integer id;

    private String name;

    private String password;

   

    private LocalDate birthday;

   

    // 省略setter/getter/toString 方法

   

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

2.2 测试用例

// 测试转换单个对象为Map 结构

@Test

public void toPropertyMap() throws SQLException {

    String str = "select id uId, name , pwd, birthday from t_user where id = 1001";

    Connection connection = DbConnUtil.getConnection(true);

    Statement statement = connection.createStatement();

    ResultSet resultSet = statement.executeQuery(str);

    LinkedHashMap<String, Object> map = ResultSetUtil.toPropertyMap(resultSet);

    map.forEach((key, val) -> System.out.println(key + ":" + val));

}

// 测试转换对象为单个bean

@Test

public void toBean() throws SQLException {

    String str = "select * from t_user where id = 1002";

    Connection connection = DbConnUtil.getConnection(true);

    Statement statement = connection.createStatement();

    ResultSet resultSet = statement.executeQuery(str);

    UserPO userPO = ResultSetUtil.toBean(resultSet, UserPO.class);

    System.out.println(userPO);

}

// 测试转换对象为bean列表

@Test

public void toBeans() throws SQLException {

    String str = "select * from t_user ";

    Connection connection = DbConnUtil.getConnection(true);

    Statement statement = connection.createStatement();

    ResultSet resultSet = statement.executeQuery(str);

    List<UserPO> userPOList = ResultSetUtil.toBeans(resultSet, UserPO.class);

    userPOList.forEach(System.out::println);

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一. Java基础部分.................................................
    wy_sure阅读 3,854评论 0 11
  • 一、基本数据类型 注释 单行注释:// 区域注释:/* */ 文档注释:/** */ 数值 对于byte类型而言...
    龙猫小爷阅读 4,295评论 0 16
  • 本节介绍Statement接口及其子类PreparedStatement和CallableStatement。 它...
    zlb阅读 1,208评论 0 0
  • 《钱本草》——张说 钱,味甘,大热,有毒。偏能驻颜,采泽流润,善疗饥,解困厄之患立验。能利邦国,亏贤达,畏...
    72e518839e4c阅读 1,263评论 0 1
  • 月儿,冷空气突然降临 渴望雪,滋润干枯的日子 却听见彼此在瞬间碎去的声音,沉重落地 携带钻入内心的冰冷,刺入骨髓 ...
    杨昊田阅读 433评论 59 50