一:什么是mybatis
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,
并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。
iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。
MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。
MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。
MyBatis 使用简单的 XML或注解用于配置和原始映射,
将接口和 Java 的POJOs(Plain Ordinary Java Objects,普通的 Java对象)映射成数据库中的记录。
二:使用mybatis替换jdbc原因
1.创建数据库user表
CREATE TABLE `user` (
`id` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名称',
`birthday` timestamp NULL DEFAULT NULL COMMENT '生日',
`sex` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别',
`address` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
2.我们先看看jdbc的代码,再看我们不使用jdbc的原因。
package com.mybatis.pojo;
import java.util.Date;
import java.util.List;
public class User {
private String id; //用户id
private String username;//用户姓名
private Timestamp birthday;//用户生日
private String sex;//用户性别
private String address;//用户地址
public User() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Timestamp getBirthday() {
return birthday;
}
public void setBirthday(Timestamp birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
package com.mybatis;
import com.mybatis.pojo.User;
import java.sql.*;
/**
* Created by user on 2019/1/24.
*/
public class JdbcUtils {
//MySQL数据库驱动
public static String driverClass = "com.mysql.jdbc.Driver";
//数据库用户名
public static String userName = "root";
//数据库密码
public static String passWord = "123";
//数据库 URL
public static String url = "jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8";
//定义数据库连接
public static Connection conn = null;
//定义声明数据库语句,使用 预编译声明 PreparedStatement提高数据库执行性能
public static PreparedStatement ps = null;
//定义返回结果集
public static ResultSet rs = null;
public static User getUserById(String id){
User user = new User();
try {
//加载数据库驱动
Class.forName(driverClass);
//获取数据库连接
conn = DriverManager.getConnection(url, userName, passWord);
//定义 sql 语句,?表示占位符
String sql = "select * from `user` where `id`=?";
//获取预编译处理的statement
ps = conn.prepareStatement(sql);
//设置sql语句中的参数,第一个为sql语句中的参数的?(从1开始),第二个为设置的参数值
ps.setString(1, id);
//向数据库发出 sql 语句查询,并返回结果集
rs = ps.executeQuery();
while (rs.next()) {
user.setId(rs.getString("id"));
user.setUsername(rs.getString("username"));
user.setAddress(rs.getString("address"));
user.setBirthday(rs.getTimestamp("birthday"));
user.setSex(rs.getString("sex"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//关闭数据库连接
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return user;
}
public static void main(String[] args) {
System.out.println(JdbcUtils.getUserById("1"));
}
}
三:分析
(如果你对mybatis还不熟悉,请暂时跳过此处分析,但是希望您掌握里mybatis的基本使用之后一定要回头看看此处分析,因为这是面试题经常问的一个问题)
通过上面的例子我们可以分析如下几点:
①、问题一:
//加载数据库驱动
Class.forName(driverClass);
//获取数据库连接
conn = DriverManager.getConnection(url, userName, passWord);
这两句代码让我们频繁的获取连接和关闭连接,造成数据库资源浪费,影响数据库性能。
解决办法:使用数据库连接池管理数据库连接
②、问题二:将 sql 语句硬编码到程序中,如果sql语句修改了,那么需要重新编译 Java 代码,不利于系统维护,也就不满足程序对扩展开放对修改关闭的条件。
解决办法:将 sql 语句配置到 xml 文件中,即使 sql 语句变化了,我们也不需要对 Java 代码进行修改,重新编译
③、问题三:在 PreparedStatement 中设置参数,对占位符设置值都是硬编码在Java代码中,不利于系统维护
解决办法:将 sql 语句以及占位符和参数都配置到 xml 文件中
④、问题四:从 resultset 中遍历结果集时,对表的字段存在硬编码,不利于系统维护
解决办法:将查询的结果集自动映射为 Java 对象
⑤、问题五:重复性代码特别多,频繁的 try-catch
解决办法:将其整合到一个 try-catch 代码块中
⑥、问题六:缓存做的很差,如果存在数据量很大的情况下,这种方式性能特别低
解决办法:集成缓存框架去操作数据库
⑦、问题七:sql 的移植性不好,如果换个数据库,那么sql 语句可能要重写
解决办法:在 JDBC 和 数据库之间插入第三方框架,用第三方去生成 sql 语句,屏蔽数据库的差异