原理分析一:JDBC到Mybatis
1.引言:
本文主要讲解什么是JDBC,从JDBC到Mybatis逐渐演变过程以及MyBatis持久框架的优点。
2.JDBC
JDBC是一种用于执行SQL语句的Java API,由java编写的一组类和接口组成。可以为多种数据库提供统一访问,为开发者屏蔽了一些细节问题。
3.JDBC操作步骤
1)加载注册驱动
2)获取连接对象
3)获取语句对象
4)执行SQL语句
5)释放资源
以下是具体实现代码:
package cn.wolfcode._02_dao_impl;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.pool.DruidDataSource;
import cn.wolfcode._02_dao.IStudentDAO;
import cn.wolfcode._02_domain.Student;
import cn.wolfcode.util.JDBCUtil;
public class StudentDAOImplPrepardStatement implements IStudentDAO {
@Override
public void insert(Student s) {
//实现对数据库插入数据
//加载驱动
//获取连接
//创建sql语句对象
//执行sql语句
//释放连接(当有连接时才释放,没有就不需要释放)
//预编译
Connection con=null;
PreparedStatement sta=null;
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdpcdemo", "root", "123456");
//String str="insert into Student values(null,'ynn',21)";
String sql="insert into Student values(null,?,?)";
sta=con.prepareStatement(sql);
sta.setString(1, s.getName());
sta.setInt(2, s.getAge());
System.out.println(sql);
sta.executeUpdate();
}catch(Exception e){
e.printStackTrace();
}finally {
if(sta!=null) {
try {
sta.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(con!=null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
@Override
public void delete(Long id) {
//实现对数据库删除数据
//加载驱动
//获取连接
//创建sql语句对象
//执行sql语句
//释放连接(当有连接时才释放,没有就不需要释放)
Connection con=null;
Statement sta=null;
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdpcdemo", "root", "123456");
sta = con.createStatement();
//String str="delete from Student where id=3";
String sql="delete from Student where id="+id;
System.out.println(sql);
sta.executeUpdate(sql);
}catch(Exception e){
e.printStackTrace();
}finally {
if(sta!=null) {
try {
sta.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(con!=null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
@Override
public void update(Student s) {
//实现对数据库删除数据
//加载驱动
//获取连接
//创建sql语句对象
//执行sql语句
//释放连接(当有连接时才释放,没有就不需要释放)
Connection con=null;
PreparedStatement sta=null;
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdpcdemo", "root", "123456");
String sql="update Student set name=?, age=? where id=?";
sta = con.prepareStatement(sql);
sta.setString(1, s.getName());
sta.setInt(2, s.getAge());
sta.setLong(3, s.getId());
//String str="update Student set name='ynn', age=22 where id=2";
sta.executeUpdate();
}catch(Exception e){
e.printStackTrace();
}finally {
if(sta!=null) {
try {
sta.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(con!=null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
@Override
public List<Student> selectAll() {
//提高作用范围
Connection con=null;
PreparedStatement ps=null;
ResultSet rs=null;
Student s=null;
List<Student> list=new ArrayList<>();
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdpcdemo", "root", "123456");
//System.out.println(con);
ps = con.prepareStatement("select * from Student");
rs = ps.executeQuery();
while(rs.next()) {
long id = rs.getLong("id");
String name = rs.getString("name");
int age = rs.getInt("age");
s=new Student(id,name,age);
list.add(s);
}
}catch(Exception e){
e.printStackTrace();
}finally {
JDBCUtil.close(rs, ps, con);
}
return list;
}
@Override
public Student selectOne(Long id) {
//提高作用范围
Connection con=null;
PreparedStatement ps=null;
ResultSet rs=null;
Student s=null;
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdpcdemo", "root", "123456");
//System.out.println(con);
String sql="select * from Student where id=?";
ps = con.prepareStatement(sql);
ps.setLong(1, id);
rs = ps.executeQuery();
while(rs.next()) {
String name = rs.getString("name");
int age = rs.getInt("age");
s=new Student(id,name,age);
//System.out.println(s);
}
}catch(Exception e){
e.printStackTrace();
}finally {
JDBCUtil.close(rs, ps, con);
}
return s;
}
}
通过以上代码分析:
4.JDBC的不足
1) 频繁的获取连接和释放连接:代码冗余不方便维护,同时造成了资源的浪费,影响了系统性能
2) sql语句分散在java类中:不利于维护,可读性差
3) sql语句查询结果返回在ResultSet中需要程序员自己取出查询数据进行封装:若不取出数据,释放资源时数据就得不到了,需要对多张表进行查询
4) 程序员需要自己处理事务来保证数据库数据的一致性
5) 频繁的处理异常:代码冗余不方便维护
5. 演变过程
1) 使用连接池从连接池中获取已经创建好的连接,用完释放到连接池中,解决了频繁获取连接和释放连接的问题,同时控制了被创建的连接的个数,一定程度上保证了数据库的安全。连接池多种多样,Java中使用javax.sql.DataSource接口来表示连接池,具体实现由服务器厂商完成。
2) 将各个功能的SQL语句放在单独的配置文件中,通过key-vaue方式获取。同时在SQL中嵌入变量(比如使用#变量名 #)传入SQL语句参数,经过解析后动态的生成符合上下文的SQL语句
3) 实现了对SQL语句的查询结果进行自动封装,不需要程序员自己封装,减少的大量的代码冗余
4) 对事务进行封装,程序员不需要自己对事务进行操作
5) 做到了只对异常处理一次
6.使用MyBatis优化总结
1) 封装了连接池,使用连接池对连接进行管理
2) 将SQL语句单独的放置在配置文件中使用key-value获取
3) 封装了对数据库操作结果的映射和结果缓存的方法,减少了大量的重复代码
4) 封装了操作事务的方法,程序员不需要自己写操作事务的代码,减少了代码的冗余
5) 只需在工具类中处理一次异常,同样减少了代码的冗余
使用MyBatis的具体实现代码:
package cn.wolfcode.dao.impl;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import cn.wolfcode.dao.IStudentDAO;
import cn.wolfcode.domain.Student;
import cn.wolfcode.util.MyBatisUtil;
public class StudentDAOImpl implements IStudentDAO {
@Override
public void insert(Student s) {
SqlSession session = MyBatisUtil.openSession();
session.insert("cn.wolfcode.mapper.insert", s);
session.commit();
session.close();
System.out.println(s);
}
@Override
public void delete(Long id) {
SqlSession session = MyBatisUtil.openSession();
session.delete("cn.wolfcode.mapper.delete", id);
session.commit();
session.close();
}
@Override
public void update(Student s) {
SqlSession session = MyBatisUtil.openSession();
session.update("cn.wolfcode.mapper.update", s);
session.commit();
session.close();
}
@Override
public Student selectOne(Long id) {
SqlSession session = MyBatisUtil.openSession();
Student s = session.selectOne("cn.wolfcode.mapper.selectOne", id);
session.commit();
session.close();
return s;
}
@Override
public List<Student> selectAll() {
SqlSession session = MyBatisUtil.openSession();
List<Student> list = session.selectList("cn.wolfcode.mapper.selectAll");
session.commit();
session.close();
return list;
}
}