传统JDBC开发模式的缺陷
传统开发模式中,在使用JDBC进行数据库连接时,一般都在引入相关的数据库驱动jar包后,创建一个数据库连接类,该类提供数据库驱动的加载、数据库连接参数配置、连接对象的获取及关闭等操作。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DBConnection{
public static final String DBDRIVER = "org.gjt.mm.mysql.Driver";
public static final String DBDURL = "jdbc:mysql://localhost:3306/mydata";
public static final String DBUSER = "root";
public static final String DBPASS = "308238";
static{
try{
Class.forName(DBDRIVER);
}catch(ClassNotFoundException e){
e.printStackTrace();
}
}
public static Connection getConnection(){
Connection conn = null;
try{
conn = DriverManager.getConnection(DBDURL,DBUSER,DBPASS);
}catch(SQLException e){
e.printStackTrace();
}
return conn;
}
public static void close(ResultSet rs, Statement st, Connection conn){
try{
if(rs!=null){rs.close();}
if(st!=null){st.close();}
if(conn!=null){st.close();}
}catch(SQLException e){
e.printStackTrace();
}
}
public static void close(Statement st,Connect conn){
close(null,st,conn);
}
}
这样会产生硬编码的问题,所谓“硬编码“,就是讲程序中的外部变量值,使用赋值语句写死在程序中,当需要修改室,要修改源码并重新编译。JDBC的代码中数据库驱动名称、数据库连接地址、数据库账号和密码都是硬编码在程序中的。
对于日常开发,需要更改数据库地址等信息时,都需要对数据库连接类的源码进行修改,这样经常变动会导致项目数据不稳定。除此之外,每一个操作数据的类都需要获取数据库连接和关闭,对数据库进行频繁的操作会造成数据库资源的浪费,十分影响数据库的性能。
public List<Teacher> getTeachers(){
List<Teacher> list = new ArrayList<Teacher>();
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = DB.getConnection();
String sql = "select * from teacher";
st = conn.createStatement();
rs = st.excuteQuery(sql);
while(rs.next()){
Teacher teacher = new Teacher();
teacher.setNumber(rs.getInt("number));
teacher.setName(rs.getString("name"));
.....
list.add(teacher);
}catch(Exception ex){
ex.printStackTrace();
}finally{
DB.close(rs,st,conn);
}
}
return list;
}
使用JDBC获取数据库数据时,使用“getString”、“getInt”等方法获取数据时,其中的参数就是表字段的名称,这也是硬编码,当数据库相应的表字段发生变化时,仍需要对源码进行修改,然后重新编译,打包和上线。
传统JDBC待优化的问题
总结传统方法存在的问题和可以解决的方案:
- 连接参数、SQL语句的硬编码:将SQL语句配置在XML或者其他非java的配置文件中,即使SQL发生变化也不需要重新编译java文件。
- 数据库的频繁连接和断开:使用数据库连接池来管理数据的连接。
- 查询结果集取数据的硬编码:使用一种机制,将查询出的结果自动映射为java对象,无需手动设置。
MyBatis介绍
MyBatis是Apache的一个java的开源项目。MyBatis是一个支持动态SQL语句的持久层框架。MyBatis将SQL语句配置在XML文件中;通过MyBatis提供输入参数映射的方式,将参数自由灵活的配置在SQL语句配置文件中;通过MyBatis的输出映射机制,将结果集的检索自动映射成相应的java对象;MyBatis还可以还可以创建自己的数据库连接池。
综上,MyBatis特点是:采用配置文件动态管理SQl语句,并含有输入映射、输出映射机制以及数据连接池配置的持久层框架。
1. 数据源配置文件
一个持久层框架就是负责连接数据库,并对数据进行操作的一系列框架。在MyBatis中,数据库的数据源配置在SqlMapConfig.xml(文件名可修改)中,其中配置了数据库驱动、数据局连接地址、数据库用户名和密码、事务管理等参数。
项目中,SqlMapConfig.xml的文件内容大致如下(最初级的配置):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="developemt">
<environment id="development">
<!--使用JDBC事务管理-->
<transactionManager type="JDBC">
<!--数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="org.gjt.mm.mysql.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydata?characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="308238"/>
</dataSource>
</environment>
</emvironments>
</configuration>
在与SpringMVC框架中,会使用SpringMVC建立数据库连接池,此时不需要MyBatis单独配置数据库连接池了。
2. SQL映射配置文件
&emspM;yBatis框架中,将SQL配置在独立的配置文件Mapper.xml(文件名可修改)中,可以配置任何类型的SQL语句,包括select、update、delete和insert语句。在输入参数方面,MyBatis会根据配置文件简直组装参数的Java对象或Map对象中的相关字段与Mapper.xml中的参数配置做匹配,将相关数据绑定到SQL语句上;在查询输出结果时,会根据Mapper.xml的结果集信息将数据库的数据字段一一映射到相应的java对象或Map对象中。
在项目中,Mapper.xml的大致内容如下:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-msqpper.dtd">
<mapper namespace="test">
<select id="findUserById" parameterType="int" resultType="cn.com.mybatis.model.User">
SELECT * FROM USER WHERE id = #{id}
</select>
</mapper>
在上述配置文件中,其中select标签对中包含了一段SQL查询语句,其中parameterType指定了输入参数的类型,而resultType指定了输出结果映射的java对象类型。
Mapper.xml的文件路径一般会配置在数据源配置文件SqlMapConfig.xml中,配置方式如下:
<mappers>
<mapper resource="sqlmap/UserMapper.xml">
<mapper resource="sqlmap/GoodsMapper.xml">
</mappers>
3. 会话工厂和会话
有了数据库连接池配置文件SqlMapConfig.xml,以及SQL映射配置文件Mapper.xml后,需要相关的程序来读取并加载这些信息。使用“会话工厂”和“会话”来处理。
在MyBatis中,“会话工厂”是SqlSessionFactory类。SqlSessionFactory会根据Resource资源信息来加载对象,获取SqlMapConfig.xml的信息,从而产生可以与数据库交互的会话实例类——SqlSession
MyBatis的运行流程
首先SqlSessionFactory会话工厂会通过Resource信息加载对象获取SqlMapConfig.xml文件信息,然后产生可以与数据库交互的会话实例类SqlSession。会话实例类SqlSession根据Mapper配置文件中得到SQL配置去执行相应的增删改查操作。在SqlSession类内,是通过Executor(分为基本执行其和缓存执行器)对数据库进行操作的。执行器与数据库交互,依靠的是底层封装对象Mappered Statement,它封装了从Mapper文件中读取的信息(包括SQL语句,输入参数,输出结果类型)。MyBatis的运行流程图如下: