MyBatis|JDBC编程中的问题、MyBatis介绍与第一个程序
学习内容来自:什么是MyBatis?业内资深大牛带你揭秘持久层框架
JDBC编程中的问题
以下的程序查询user表中username=sally的数据:
public class JdbcTest {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/user"+"?serverTimezone=GMT%2B8",
"root", "123456");
String sql = "select * from tb_user WHERE username=?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, "sally");
resultSet = preparedStatement.executeQuery();
while(resultSet.next()) {
System.out.println(resultSet.getString(1) + "密码是:" + resultSet.getString(2));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
观察以上程序,发现JDBC编程有如下几个问题:
1. 将sql语句硬编码到java代码,不利于系统维护。
String sql = "select * from tb_user WHERE username=?";
设想如何解决:将sql单独抽取出来,在配置文件(xml方式、properties文件)进行配置。
2. 数据库连接不能重复利用,对数据库资源是一种浪费。
设想如何解决:使用数据库连接池管理数据库连接。
3. 向Statement设置参数时,参数的位置通过硬编码指定。
preparedStatement.setString(1, "sally");
设想如何解决:是否能够根据一些配置,自动将 java 对象的值设置到Statement。
4. 遍历结果集时,resultSet.getString() 通过硬编码指定列。
System.out.println(resultSet.getString(1) + "密码是:" + resultSet.getString(2));
设想如何解决:能否自动将 sql 查询结果集映射成 java 对象。
Mybatis框架
MyBatis 本是 apache 的一个开源项目 iBatis, 2010年这个项目由 apache software foundation 迁移到了google code,并且改名为 MyBatis。
Mybatis是一个不完全的 orm 框架,mybatis 也可以进行对象关系映射,但是还需要手动写 sql 语句。
Hibernate是一个完全的优秀的 orm 框架,hibernate 完全实现,java对象 到 关系 的映射。sql 不需要手动编写。
注:对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的–“虚拟对象数据库”。
下图为Mybatis框架图:
其中:
- SqlMapConfig.xml 是 mybatis 核心配置文件
配置了数据源(连接池)、事务 - SqlSessionFactory会话工厂
用于生产会话 SqlSession - SqlSession会话
是一个面向用户的门面接口,用于操作数据库(增、删、改、查) - Executor执行器
SqlSession 内部是通过 Executor 操作数据库
Executor 是一个底层的封装对象,用户看不到。
Executor 需要使用 Mapped Statement 中封装的数据信息来操作数据库。 - Mapped Statement
是 Mybatis 一个封装对象,也是一个底层封装对象(用户是看不到),封装了 sql 语句、传入 sql 语句的参数,将 sql 查询结果映射(输出)成的 java 对象。
Mybatis 解决JDBC编程的问题
-
数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。
解决:在SqlMapConfig.xml中配置数据连接池,使用连接池管理数据库链接。 -
Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。 -
向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。 -
对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。
如下所示:User.xml
<!-- 写sql语句 -->
<mapper namespace="test">
<!-- 通过ID查询一个用户 -->
<select id="findUserById" parameterType="Integer" resultType="cn.itcast.mybatis.pojo.User">
select * from user where id = #{v}
</select>
</mapper>
Mybatis 与 Hibernate 不同(面试问题)
-
Hibernate是一个完全的优秀的 orm 框架,hibernate 完全实现,java对象 到 关系 的映射。sql 不需要手动编写。
Mybatis是一个不完全的 orm 框架,mybatis 也可以进行对象关系映射,但是还需要手动写 sql 语句。
Mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。 -
Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是Mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。
Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。
总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。