01.MyBatis学习笔记

传统 JDBC 的弊端

Posted by Chen Xingxu on September 15, 2020

01.MyBatis学习笔记–传统 JDBC 的弊端

JDBC 执行流程

  1. 加载 JDBC 驱动;
  2. 建立并获取数据库连接;
  3. 创建 JDBC Statements 对象;
  4. 设置 SQL 语句的传入参数;
  5. 执行 SQL 语句并获得查询结果;
  6. 对查询结果进行转换处理并将处理结果返回;
  7. 释放相关资源(关闭 Connection,关闭 Statement,关闭 ResultSet);

执行流程示例代码:

public static List<Map<String,Object>> queryForList(){  
    Connection connection = null;  
    ResultSet rs = null;  
    PreparedStatement stmt = null;  
    List<Map<String,Object>> resultList = new ArrayList<Map<String,Object>>();  

    try {  
        // 加载 JDBC 驱动  
        Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();  
        String url = "jdbc:oracle:thin:@localhost:1521:ORACLEDB";  

        String user = "trainer";   
        String password = "trainer";   

        // 建立并获取数据库连接 
        connection = DriverManager.getConnection(url,user,password);   

        String sql = "select * from userinfo where user_id = ? ";  
        // 创建 JDBC Statements 对象(每一个Statement为一次数据库执行请求)  
        stmt = connection.prepareStatement(sql);  

        // 设置 SQL 语句的传入参数  
        stmt.setString(1, "zhangsan");  

        // 执行 SQL 语句并获得查询结果 
        rs = stmt.executeQuery();  

        // 对查询结果进行转换处理并将处理结果返回(将查询结果转换成List<Map>格式)  
        ResultSetMetaData rsmd = rs.getMetaData();  
        int num = rsmd.getColumnCount();  

        while(rs.next()){  
            Map map = new HashMap();  
            for(int i = 0;i < num;i++){  
                String columnName = rsmd.getColumnName(i+1);  
                map.put(columnName,rs.getString(columnName));  
            }  
            resultList.add(map);  
        }  

    } catch (Exception e) {  
        e.printStackTrace();  
    } finally {  
        try {  
            // 关闭 ResultSet 
            if (rs != null) {  
                rs.close();  
                rs = null;  
            }  
            // 关闭 Statement  
            if (stmt != null) {  
                stmt.close();  
                stmt = null;  
            }  
            //关闭 Connection
            if (connection != null) {  
                connection.close();  
                connection = null;  
            }  
        } catch (SQLException e) {  
            e.printStackTrace();  
        }  
    }        
    return resultList;  
}

传统 JDBC 的弊端

  1. JDBC 底层没有用连接池,操作数据库需要频繁的创建和关闭连接,消耗很大的资源;
  2. 原生的 JDBC 代码在 Java 中,一旦需要修改 SQL,Java 需要整体编译,不利于系统维护;
  3. 使用 PreparedStatement 预编译的话,对变量进行设置 1、2、3 等数字,这样的序号不利于维护;
  4. 返回 result 结果集也需要硬编码。

JDBC DEMO

Maven 配置

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>demo.yangxu</groupId>
    <artifactId>yangxu-mybatis-demo-01</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <slf4j.version>1.6.1</slf4j.version>
        <logback.version>1.1.2</logback.version>
        <mysql-connector-java.version>5.1.30</mysql-connector-java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql-connector-java.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>${logback.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>

                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
                
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.7.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.20.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>

业务类

建表 SQL

CREATE TABLE `mybatis_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `username` varchar(255) DEFAULT NULL COMMENT '姓名',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  `phone` bigint(20) DEFAULT NULL COMMENT '电话号码',
  `desc` varchar(255) DEFAULT NULL COMMENT '描述',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4;

User

package demo.yangxu.jdbc;

import java.io.Serializable;

public class User implements Serializable {
    private Integer id;
    private String username;
    private  Integer age;
    private String phone;
    private  String desc;

    //Getter和Setter方法略
    //toString方法略
}

DbUtil

package demo.yangxu.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DbUtil {
    /*
     * 打开数据库
     */
    private static String driver;//连接数据库的驱动
    private static String url;
    private static String username;
    private static String password;

    static {
        driver="com.mysql.jdbc.Driver";//需要的数据库驱动
        //url="jdbc:mysql://127.0.0.1:3306/mybatis_learn?characterEncoding=utf8&amp;serverTimezone=UTC&amp;useSSL=false";
        //url="jdbc:mysql://127.0.0.1:3306/mybatis_learn?characterEncoding=utf8&serverTimezone=UTC&useSSL=false";
        url="jdbc:mysql://127.0.0.1:3306/mybatis_learn";//数据库名路径
        username="root";
        password="root123456";
    }
    public static Connection open()
    {
        try {
            Class.forName(driver);
            return (Connection) DriverManager.getConnection(url,username, password);
        } catch (Exception e) {
            System.out.println("数据库连接失败!");
            e.printStackTrace();
        }//加载驱动

        return null;
    }

    /*
     * 关闭数据库
     */
    public static void close(Connection conn)
    {
        if(conn!=null)
        {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

测试 JDBC

Jdbc01

package demo.yangxu.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/***
 * 非对象
 */
public class Jdbc01 {
    public static void main(String[] args) {

        insert("Yangxu002",30);
    }

    static void insert(String name,int age)
    {
        String sql="insert into mybatis_user(username,age) value(?,?)";
        Connection conn=DbUtil.open();
        try {
            PreparedStatement pstmt=(PreparedStatement) conn.prepareStatement(sql);
            pstmt.setString(1,name);
            pstmt.setInt(2,age);
            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        finally {
            DbUtil.close(conn);
        }

    }
}

Jdbc02

package demo.yangxu.jdbc;

import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.sql.PreparedStatement;

import java.sql.ResultSet;
import java.sql.SQLException;

/***
 * 面向对象
 */
@Slf4j
public class Jdbc02 {
    public static void main(String[] args) {
        User c=new User();
        c.setUsername("Yangxu005");
        c.setAge(30);
        insert(c);
        //查询
        c=query(11);
        log.info("userid:{},name:{}",c.getId(),c.getUsername());
    }

    static void insert(User c)
    {
        String sql="insert into mybatis_user(username,age) value(?,?)";
        Connection conn=DbUtil.open();
        try {
            PreparedStatement pstmt=(PreparedStatement) conn.prepareStatement(sql);
            pstmt.setString(1,c.getUsername());
            pstmt.setInt(2,c.getAge());
            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        finally {
            DbUtil.close(conn);
        }


    }

    static User query(int id)
    {
        String sql="select * from mybatis_user where id=?";
        Connection conn=DbUtil.open();
        try {
            PreparedStatement pstmt=(PreparedStatement) conn.prepareStatement(sql);
            pstmt.setInt(1,id);
            ResultSet rs=pstmt.executeQuery();
            if(rs.next())
            {
                String name=rs.getString(2);
                User c=new User();
                c.setId(id);
                c.setUsername(name);
                return c;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        finally {
            DbUtil.close(conn);
        }
        return null;
    }
}