【MyBatis深入学习】深入浅出MyBatis技术原理与实战(1)

1.传统JDBC编程

java程序都是通过JDBC(java Data Base Connectivity)连接数据库的,这样就可以通过SQL对对数据库进行编程。它是一套面向对象的应用程序接口(API),并且制定了统一的访问各类关系数据库的标准接口,为各个数据库厂商提供了标准的接口实现。通过使用JDBC技术,开发人员可以用纯Java语言和标准的SQL语句编写完整的数据库应用程序,真正地实现软件的跨平台。
这里写图片描述
JDBC对多种关系型数据库的驱动和操作都进行了封装,因此,开发者不需要编写额外的程序来兼容不同的数据库连接,只需要通过加载不同的数据库驱动程序即可完成连接,我们首先简单地封装JDBC连接类:

import java.sql.Connection;  
import java.sql.DatabaseMetaData;  
import java.sql.DriverManager;  
import java.sql.ResultSet;  
import java.sql.SQLException;  
import java.sql.Statement;  

import oracle.jdbc.driver.OracleConnection;  

/** 
 * @Description: JDBC连接类(示例连接Oralce) 
 * @CreateTime: 2017-10-19 下午9:46:44 
 * @author: pjk
 * @version V1.0 
 */  
public class JdbcUtil {  
    //驱动名    
    private static String DRIVER = "oracle.jdbc.driver.OracleDriver";    
    //获得url    
    private static String URL = "admin";    
    //获得连接数据库的用户名    
    private static String USER = "jdbc:oracle:thin:@localhost:7001:test";    
    //获得连接数据库的密码    
    private static String PASS = "";    

    static {    
        try {     
            //1.初始化JDBC驱动并让驱动加载到jvm中,加载JDBC驱动后,会将加载的驱动类注册给DriverManager类。  
            Class.forName(DRIVER);    
        } catch (ClassNotFoundException e) {    
            e.printStackTrace();    
        }    
    }    

     public static Connection getConnection(){    
        Connection conn = null;    
        try {     
            //2.取得连接数据库    
            conn = DriverManager.getConnection(URL,USER,PASS);    
            //3.开启自动提交  
            conn.setAutoCommit(true);  
        } catch (SQLException e) {    
            e.printStackTrace();    
        }    
        return conn;    
     }    

    //开启事务  
    public static void beginTransaction(Connection conn) {    
        if (conn != null) {    
            try {    
                if (conn.getAutoCommit()) {    
                    conn.setAutoCommit(false);    
                }    
            } catch (SQLException e) {    
                e.printStackTrace();    
            }    
        }    
    }    

    //提交事务  
    public static void commitTransaction(Connection conn) {    
        if (conn != null) {    
            try {    
                if (!conn.getAutoCommit()) {    
                    conn.commit();    
                }    
            } catch (SQLException e) {    
                e.printStackTrace();    
            }    
        }    
    }    

    //回滚事务  
    public static void rollBackTransaction(Connection conn) {    
        if (conn != null) {    
            try {    
                if (!conn.getAutoCommit()) {    
                    conn.rollback();    
                }    
            } catch (SQLException e) {    
                e.printStackTrace();    
            }    
        }    
    }    

     //关闭连接  
     public static void close(Object o){    
        if (o == null){    
            return;    
        }    
        if (o instanceof ResultSet){    
            try {    
                ((ResultSet)o).close();    
            } catch (SQLException e) {    
                e.printStackTrace();    
            }    
        } else if(o instanceof Statement){    
            try {    
                ((Statement)o).close();    
            } catch (SQLException e) {    
                e.printStackTrace();    
            }    
        } else if (o instanceof Connection){    
            Connection c = (Connection)o;    
            try {    
                if (!c.isClosed()){    
                    c.close();    
                }    
            } catch (SQLException e) {    
                e.printStackTrace();    
            }    
        }      
    }    

    //重载关闭连接  
    public static void close(ResultSet rs, Statement stmt,     
            Connection conn){    
        close(rs);    
        close(stmt);    
        close(conn);    
    }    
    //重载关闭连接  
    public static void close(ResultSet rs,     
            Connection conn){    
        close(rs);     
        close(conn);    
    }   
    //重载关闭连接  
    public static void close(ResultSet rs, PreparedStatement ps,     
            Connection conn){    
        close(rs);    
        close(ps);    
        close(conn);    
    }    
}  

JDBC数据库连接的查询主要通过Statement对象来执行各种SQL语句。Statement对象主要分为以下3种类型:

1. Statement :执行静态SQL语句的对象。

Statement接口常用的2个方法:
(1) executeUpdate(String sql) :执行insert / update / delete 等SQL语句,成功返回影响数据库记录行数的int整数型。
(2) executeQuery(String sql) : 执行查询语句,成功返回一个ResultSet类型的结果集对象。

ResultSet rs = null;  
Statement stmt = null;  
try {  
    stmt = conn.createStatement();  
    int num = stmt.executeUpdate("insert into company values('No.1','CSDN')");  
    rs = stmt.executeQuery("select * from company");  
} catch (SQLException e) {  
    // TODO Auto-generated catch block  
    e.printStackTrace();  
        conn.rollback();  
}finally{  
    JdbcUtil.close(rs, stmt, conn);  
}

1.1 Statement批量处理函数:

(1) addBatch(String sql) :添加批量处理的数据;
(2) executeBatch():提交批量数据;
(3) clearBatch():清空已添加的批量数据;

/** 
  * 实验一:Statement.executeBatch(); 
  */  
ResultSet rs = null;  
Statement stmt = null;  
try {  
    conn.setAutoCommit(false); //切记:必须设置成手动提交模式,否则每次addBatch都会提交一次,而不是批量提交  
    stmt = conn.createStatement();  
    Long startMemory  = Runtime.getRuntime().freeMemory();  
    Long startTime = System.currentTimeMillis();   
    for(int i = 0; i < 10000; i++){  
        stmt.addBatch("insert into t_dept values('No.1','CSDN')");  
        //stmt.executeUpdate("insert into t_dept values('No.1','CSDN')");  
    }  
    stmt.executeBatch();  
    conn.commit();  
    Long endMemory = Runtime.getRuntime().freeMemory();  
    Long endTime = System.currentTimeMillis();   
    System.out.println("使用内存大小:"+ (startMemory-endMemory)/1024 + "KB");  
    System.out.println("用时:"+ (endTime-startTime)/1000 + "s");  
} catch (SQLException e) {  
    e.printStackTrace();  
    conn.rollback();  
}finally{  
    JdbcUtil.close(rs, stmt, conn);  
}  

//执行结果:  
使用内存大小:488KB  
用时:116s   --汗,原谅我的电脑龟速。
/** 
  * 实验二:Statement.executeUpdate(); 
  */  
//而如果直接使用executeUpdate更新(其实一样是批量提交),竟然比executeBatch速度更快,效率更高,这个真的百思不得其解,留待以后解决。。  
ResultSet rs = null;  
Statement stmt = null;  
try {  
    conn.setAutoCommit(false); //切记:必须设置成手动提交模式,否则每次addBatch都会提交一次,而不是批量提交  
    stmt = conn.createStatement();  
    Long startMemory  = Runtime.getRuntime().freeMemory();  
    Long startTime = System.currentTimeMillis();   
    for(int i = 0; i < 10000; i++){  
            //stmt.addBatch("insert into t_dept values('No.1','CSDN')");  
        stmt.executeUpdate("insert into t_dept values('No.1','CSDN')");  
    }  
    //stmt.executeBatch();  
    conn.commit();  
    Long endMemory = Runtime.getRuntime().freeMemory();  
    Long endTime = System.currentTimeMillis();   
    System.out.println("使用内存大小:"+ (startMemory-endMemory)/1024 + "KB");  
    System.out.println("用时:"+ (endTime-startTime)/1000 + "s");  
} catch (SQLException e) {  
    e.printStackTrace();  
    conn.rollback();  
}finally{  
    JdbcUtil.close(rs, stmt, conn);  
}  
//执行结果:  
<span style="font-family: Arial, Helvetica, sans-serif;">使用内存大小:329KB</span>  
用时:98s 

Note:本次实验得出的结论是使用executeUpdate的批量提交法比executeBatch效率高,速度更快,占用内存更小,如果有朋友有不同结论的话,欢迎留言交流。

1.2 Statement可滚动ResultSet配置:

(1) java.sql.Connection.creatStatement(int resultSetType,int resultSetConcurrency);
(2) java.sql.Connection.creatStatement(int resultSetType,int resultSetConcurrency,int resultSetHoldability);
参数:
[1] resultSetType: – 生成的ResultSet的类型
ResultSet.TYPE_FORWARD_ONLY – 结果集只允许向前滚动,默认缺省值
ResultSet.TYPE_SCROLL_INSENSITIVE – 结果集对数据库中的的数据变动是不敏感的
ResultSet.TYPE_SCROLL_SENSITIVE – 结果集对数据库中的的数据变动是敏感的(实际上只对Update的数据敏感)
Note:
ResultSet为TYPE_SCROLL_INSENSITIVE时,我们取出的是数据库中真实数据,并且保存在内存中,一旦取出后,数据库中数据进行变动将不能及时更新到ResultSet中; 而ResultSet为TYPE_SCROLL_SENSITIVE时,我们取出的是数据库中数据的索引值(类似于rowid),每次rs.next()时将根据该索引时重新从数据库中取出数据,所以说是敏感的,但是如果数据库中进行的是添加或是删除操作,那敏感性也将无效。(自己思考,索引值)
[2] resultSetConcurrency: – 生成的ResultSet的并发性(指定是否可修改ResultSet结果集)
ResultSet.CONCUR_READ_ONLY – 结果集不可修改(只读),默认缺省值
ResultSet.CONCUR_UPDATABLE – 结果集可修改

ResultSet rs = null;  
PreparedStatement ps;  
try {  
    ps = conn.prepareStatement("insert into company values(?,?)");  
    ps.setString(1, "No1.");  
    ps.setString(2, "csdn");  
    int num = ps.executeUpdate();  
} catch (SQLException e) {  
    // TODO Auto-generated catch block  
    e.printStackTrace();  
        conn.rollback();  
}finally{  
    JdbcUtil.close(rs, stmt, conn);  
}  

try {  
    ps = conn.prepareStatement("select * from company");  
    ps.setString(1, "No1.");  
    ps.setString(2, "csdn");  
    rs = ps.executeQuery();  
} catch (SQLException e) {  
    // TODO Auto-generated catch block  
    e.printStackTrace();  
        conn.rollback();  
}finally{  
    JdbcUtil.close(rs, stmt, conn);  
}  

优点:(1)可以有效SQL注入式攻击,提高安全性。(2)使用预处理语句在性能上提升很多。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值