DBUtil向myBatis映射的解析

本文介绍了DAButil框架的工作原理,包括更新与查询方法的实现细节,并探讨了其与MyBatis之间的相似之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 其实本质上,这个DAButil和我所想的几乎是差不多的就是只不过考虑的更复杂而已,这个主要将这个分为了修改和查找两个部分,他就是利用数据的元数据,可以获取到数据替换参的个数,而元数据作为底层的更接触到数据的本质所以,对数据的类型并不会做特殊的要求所以,才会产生这样的结果。

  • 这个方法仅仅用于增删改主要原因查找和增删改执行的两个方法是不同的所以不得不采用两个方法

    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
    public void update(String sql, Object[] args) {

    Connection conn = null;
    PreparedStatement stmt = null;

    try {

    conn = ds.getConnection();

    stmt = conn.prepareStatement(sql);

    ParameterMetaData pmd = stmt.getParameterMetaData();

    // 拿到占位符个数
    int count = pmd.getParameterCount();

    // 替换占位符
    if (count > 0) {

    // 说明有占位符

    if (args == null) {

    // throw new
    // IllegalArgumentException("sorry, the parameter is wrong..");
    throw new IllegalArgumentException(
    "对不起, 你传的参数 有问题, 不要瞎 搞 ...");
    }

    if (count != args.length) {
    throw new IllegalArgumentException(
    "对不起, 你传的参数个数 与 占位符 个数 不匹配 , 不要瞎 搞 ...");
    }

    // for 循环去 替换占位符
    for (int i = 0; i < args.length; i++) {

    stmt.setObject(i + 1, args[i]);
    }
    }

    stmt.executeUpdate();

    } catch (Exception e) {
    e.printStackTrace();
    // 自定义异常 , 一般都是 自定义 异常去继承 RuntimeException
    throw new MyRuntimeException(e);

    } finally {

    // 释放资源
    release(null, stmt, conn);
    }

    }

  • 查询的方法
  • 对于查询和增删改的原理差不多,
    1. 首先获取数据的占位符的个数,我们
  • 只不过需要指定返回结果的类型,在这个类型中我们需要传递一个接口的实现类
  • 最后返回接口的结果
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
public Object query(String sql, Object[] args,ResultSetHandler rsh){

Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs =null;

try {

conn = ds.getConnection();

stmt = conn.prepareStatement(sql);

ParameterMetaData pmd = stmt.getParameterMetaData();

// 拿到占位符个数
int count = pmd.getParameterCount();

// 替换占位符
if (count > 0) {

// 说明有占位符

if (args == null) {

// throw new
// IllegalArgumentException("sorry, the parameter is wrong..");
throw new IllegalArgumentException(
"对不起, 你传的参数 有问题, 不要瞎 搞 ...");
}

if (count != args.length) {
throw new IllegalArgumentException(
"对不起, 你传的参数个数 与 占位符 个数 不匹配 , 不要瞎 搞 ...");
}

// for 循环去 替换占位符
for (int i = 0; i < args.length; i++) {

stmt.setObject(i + 1, args[i]);
}
}

// 走到这, 接下来 , 怎么弄?
// 碰到 这个地方, 不好操作了, 因为 不知道 调用者 调用这个方法 去查询时 ,到底是要返回多个的值,还是返回 单个值
// 就需要告诉调用者, 自己去操作了 .
rs = stmt.executeQuery();

return rsh.handle(rs);
} catch (Exception e) {
e.printStackTrace();
// 自定义异常 , 一般都是 自定义 异常去继承 RuntimeException
throw new MyRuntimeException(e);

} finally {

// 释放资源
release(rs, stmt, conn);
}

}

实现类的接口:规定了传递的结果:

接口也会是对于他的结果的格式一个规定,参数的类型以及返回的结果

1
2
3
4
5
6
7
8
9
10
11
12
import java.sql.ResultSet;
/*
* 这个是 结果集处理器, 定义的一个接口, 并且这个接口 接受了 一个参数, 就是 查询的结果集, 将来, 调用者 调用 了 Qyuery方法 的时候,
* 就知道 要传 这个接口一个 实现类进来, 那么 就知道 要自己去写接口中的算法, 并且 在这个过程中,将 查询的结果集 也 传递给了接口.
* 那么 就有了 可以自己去操作的结果集数据了 .
*
*/
public interface ResultSetHandler {

Object handle(ResultSet rs);

}

接口的实现类:

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
package com.itheima.dbassist.handler;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

import com.itheima.dbassist.exception.MyRuntimeException;

/*
* 返回 满足的单个的查询的 接口 实现类
*
*/

public class BeanHandler implements ResultSetHandler {

private Class clazz;

public BeanHandler(Class clazz){
this.clazz= clazz;
}

@Override
public Object handle(ResultSet rs) {

List list = new ArrayList();

try {
ResultSetMetaData rsmd = rs.getMetaData();


//目标 要封装数据的 bean
Object bean = clazz.newInstance();

if(rs.next()){

//拿到 列的数量
int columnCount = rsmd.getColumnCount();

for (int i = 1; i <=columnCount; i++) {

//拿到 当前 i 这列的值
Object value = rs.getObject(i);

//列的名称
String columnName = rsmd.getColumnName(i);

//由于 列的名称和 列 值 与 目标bean的 字段的名称和 值的类型 一致, 所以 可以 使用反射 去封装

Field declaredField = clazz.getDeclaredField(columnName);

//打开访问权限
declaredField.setAccessible(true);

declaredField.set(bean, value);
}
}

return bean;
} catch (Exception e) {

throw new MyRuntimeException(e);
}
}

}
  • 返回的是一个结果集
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
package com.itheima.dbassist.handler;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

import com.itheima.dbassist.exception.MyRuntimeException;
/*
* 用于 返回 满足 多个 的 处理器的 封装的实现类 ,当 调用者 需要 查询多个 值的时候, 就可以使用这个 实现类 ,这个实现类 帮组去完成 封装的操作
*
* 规定 :  你需要将 封装数据到哪个 javabean上 你得 告诉 我, 目标 javabean的字段的名称以及 类型 需要与 数据库中的表的 字段的名称和类型保持 一致
*
*/
public class BeanListHandler implements ResultSetHandler {

private Class clazz;

public BeanListHandler(Class clazz){
this.clazz= clazz;
}

@Override
public Object handle(ResultSet rs) {

List list = new ArrayList();

try {
ResultSetMetaData rsmd = rs.getMetaData();


while(rs.next()){

//目标 要封装数据的 bean
Object bean = clazz.newInstance();

//拿到 列的数量
int columnCount = rsmd.getColumnCount();

for (int i = 1; i <=columnCount; i++) {

//拿到 当前 i 这列的值
Object value = rs.getObject(i);

//列的名称
String columnName = rsmd.getColumnName(i);

//由于 列的名称和 列 值 与 目标bean的 字段的名称和 值的类型 一致, 所以 可以 使用反射 去封装

Field declaredField = clazz.getDeclaredField(columnName);

//打开访问权限
declaredField.setAccessible(true);

declaredField.set(bean, value);
}
list.add(bean);
}

return list;
} catch (Exception e) {
throw new MyRuntimeException(e);
}
}

}
  • 总结:通过dbutile的简单的框架,我感觉mybatis的原理是与他类似的,主要他的配置文件config获取加载后的xml文件,获取初始化的信息,之后通过obeject factory 进行创建在查询 数据所需要的实体类对象以及中间的对象,refect通过反射调用实体类对象进行对象的赋值,在这个过程中,我认为需要对类型的转化,数据库的jdbc的类型转换到java的类型所以他设计了一个typehander的类型处理器来解决这个问题,当然这个框架也会设计数据库的事务处理,以及数据检索操作的优化问题,其中包括对于缓存机制的设置,也就是同时操作一条数据以后对查询的内容不会频繁的操作数据库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值