JavaEE MyBatis (一) 基础概念

1. 什么是框架?

MyBatis 就是一个操作数据库的框架,框架就是软件功能的半成品,框架提供了一个软件项目中通用的功能,将大多数常见的功能进行封装,无需自己重复开发。

2. 什么是对象关系映射?

MyBatis 是一个基于 “ORM” 的框架,ORM 的全称是对象关系映射(Object Relational Mapping).

对象(Object)就是Java中的对象,关系(Relational)就是数据库中的数据表,基于 “ORM” 的框架是把数据在对象和关系之间进行双向转换。

ORM 的细节可以从 3 个方面来介绍:

(1)1 个类 对应 1 个表。

(2)1 个类的对象 对应 表中的一行。

(3)1 个类的对象中的属性 对应 1 个表中的列。

ORM 映射关系如图 1-1 所示。

MyBatis 框架可以将 Java 类中的数据转化为数据表中的记录,或者将数据表中的记录封装到 Java 类中,过程如图 1-2 所示:

从图 1-2 的过程来看,程序员不再直接使用 JDBC 对象访问数据库,而是以面向对象的方式来使用实体类,对实体类进行的增加、删除、更新和查询操作都会由 ORM 框架转化成对数据库的增加、删除、更新和查询操作。

ORM 框架内部的核心技术的原理其实就是 JDBC 和 反射,这个技术是由 ORM 框架、也就是 MyBatis 来进行封装的。

3. MyBatis 的优势

MyBatis 是现阶段操作数据库的主流框架,此框架的主要作用就是更加便捷地操作数据库。它具有很多优势,具体体现在以下 7 个方面:

(1)ROW 行 与 Entity 实体类双向转换:可以将数据表中的 ROW 行与 Entity 实体类进行互相转换,比如将 ResultSet 对象返回的数据自动封装到 Entity 实体类 或 List 中,或将 Entity 实体类中的数据转换成数据表中新的一行 ROW。

(2)SQL语句 与 Java文件 分离: 可以把 SQL 语句写到 XML 文件中,目的是将 SQL语句 与 Java文件 分离,使代码分层更明确。

(3)允许对 SQL语句 进行自定义优化:因为 MyBatis框架 是使用 SQL语句 对数据库进行操作的,所以可以单独地对 SQL语句 进行优化,以提高操作效率。

(4)减化 DAO层 代码:在使用传统的 JDBC 开发方式时,需要写上必要的 DAO层 代码以对数据库进行操作,但冗余代码太多,所以 MyBatis 解决了这个问题。使用 MyBatis 做查询时可以自动将数据表中的数据记录封装到 实体类 或 Map 中,再将它们放入 List 进行放回。

(5)半自动化所带来的灵活性: MyBatis 是 “半自动化” 的 “ORM” 框架,但它应该算作 SQL映射框架(SQL Mapper Framework)。将 MyBatis 称为 “半自动化的 ORM 框架” 是因为 MyBatis 操作数据库时还是使用原始的 SQL 语句,这些 SQL语句 还需要程序员自己来进行设计,这就是半自动化。

(6)支持 XML 或 Annotation 注解的方式进行 ORM :MyBatis 可以使用 XML 或 Annotations注解的方式 将数据表中的记录 映射成 1 个 Map 或 Java POJO 实体类对象,但推荐使用 XML 方式。

(7)功能丰富:MyBatis 还可以实现自定义 SQL 段落、调用存储过程和进行高级映射等功能。

4. ORM 的原理实现

本章将用代码来模拟实现一个微型的 ORM 功能。

4.1 使用 JDBC 和反射技术实现泛型 DAO

MyBatis 实现 ROW 行与 Entity实体类双向转换的原理是基于 JDBC 和 反射技术,MyBatis 框架只是对 JDBC 技术进行了轻量级的封装,使程序员更方便地区操作数据库。

创建获得 Connection 连接对象,代码如下:

public class GetConnection {
    public static Connection getConnection() throws ClassNotFoundException, SQLException {
        // 使用 oracle驱动器
        String driverName = "oracle.jdbc.OracleDriver";
        String url = "jdbc:oracle:thin:@localhost:1521:orcl";
        String username = "y2";
        String password = "123";
        Class.forName(driverName);//Class.forName(String) 返回与给定字符串名称的类或接口相关联的 Class对象。
        Connection conn = DriverManager.getConnection(url, username, password);
        return conn;
    }
}

创建实体类 Userinfo,核心代码如下:

public class Userinfo {
    private long id;
    private String username;
    private String password;
    
    public Userinfo(long id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }
    
    //省去 get 和 set 方法
}

创建泛型 DAO 类 BaseDAO,代码如下:

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class BaseDao<T> {
    // 此方法模拟了 MyBatis 的 save() 方法
    // MyBatis 框架内部的核心和本示例基本一样
    // 使用的技术就是 JDBC 和 反射
    public void save(T t)
                throws IllegalArgumentException, IllegalAccessException,
            ClassNotFoundException, SQLException {
        String sql = "insert into";
        String colName = "";
        String colParam = "";
        String begin = "(";
        String end = ")";
        Class classRef = t.getClass(); //反射获取 t 的类对象
        String tableName=classRef.getSimpleName().toLowerCase(); //getSimpleName获取具体类名称,如main
        sql = sql + tableName;
        List values = new ArrayList();
        Field[] fieldArray = classRef.getDeclaredFields();// 返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定声明字段。 
        for (int i = 0; i < fieldArray.length; i++) {
            Field eachField = fieldArray[i];
            eachField.setAccessible(true); //跳过连通性检验
            String eachFieldName = eachField.getName();
            Object eachValue = eachField.get(t);
            colName = colName + "," + eachFieldName;
            colParam = colParam + ",?";
            values.add(eachValue);
        }
        colName = colName.substring(1);
        colParam = colParam.substring(1);
        sql = sql + begin + colName + end;
        sql = sql + " values" + begin + colParam + end;
        System.out.println(sql);
        for (int i = 0; i < values.size(); i++) {
            System.out.println(values.get(i));
        }

        Connection conn = GetConnection.getConnection();
        PreparedStatement ps = conn.prepareStatement(sql); //JDBC 的预编译函数
        for (int i = 0; i < values.size(); i++) {
            ps.setObject(i + 1, values.get(i)); //批处理
        }
        ps.executeUpdate();
        ps.close();
        conn.close();
    }
    //Mybatis 的 get() 方法
      ...  
    //Mybatis 的 update() 方法
      ...  
    //Mybatis 的 delete() 方法
      ...  
    //由于方法实现大致类似,故在此省略
}

增加记录的代码如下:

public class Insert {
    public static void main(String[] args) 
            throws IllegalArgumentException, IllegalAccessException, 
            ClassNotFoundException, SQLException {
        Userinfo userinfo = new Userinfo();
        userinfo.setId(1000L);
        userinfo.setPassword("中国人");
        userinfo.setUsername("中国");
        BaseDao<Userinfo> dao = new BaseDao<Userinfo>();
        dao.save(userinfo);
    }
}

以上代码的作用就是使用 JDBC 结合反射技术来将数据表中的 1 行记录和实体类进行双向转换,这也是 ORM 框架的原理。以上代码用到了 JDBC(结合)反射技术,MyBatis 实现 ORM 的原理就是 JDBC 和 反射技术。

4.2 操作 XML 文件

XML,全称是 eXtensible Markup Language(可扩展标记语言),它可以自定义标记名称与内容,在灵活度上相比相比 HTML 有大幅提高,经常用在配置以及数据交互领域。

XML具体语法及操作

Java 读取 XML 文件中的内容

原文地址:https://www.cnblogs.com/john1015/p/13928579.html