jdbc实现类mybatis结果集解析

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

1. 工具类源码

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

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

public static LinkedHashMap 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 toPropertyMap(ResultSet resultSet) throws SQLException {

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

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

        LinkedHashMap 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 toBean(ResultSet resultSet, Class clz) {

        try {

            LinkedHashMap 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 List toBeans(ResultSet resultSet, Class clz) throws SQLException {

        List list = new ArrayList<>();

        LinkedHashMap 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 newInstance(Class clz, HashMap propertiesMap, DateTypeConverter typeConverter){

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

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

            return null;

        }

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

        T t = null;

        try {

            t = clz.newInstance();

            for (Map.Entry 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 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 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

你可能感兴趣的:(jdbc实现类mybatis结果集解析)