1 什么是 MyBatis
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOS(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
2 使用jdbc编程问题总结
(1) 创建数据库
CREATE TABLE `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL COMMENT '下单用户id',
`number` varchar(32) NOT NULL COMMENT '订单号',
`createtime` datetime NOT NULL COMMENT '创建订单时间',
`note` varchar(100) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
KEY `FK_orders_1` (`user_id`),
CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
INSERT INTO `orders` VALUES ('3', '1', '1000010', '2015-02-04 13:22:35', null);
INSERT INTO `orders` VALUES ('4', '1', '1000011', '2015-02-03 13:22:41', null);
INSERT INTO `orders` VALUES ('5', '10', '1000012', '2015-02-12 16:13:23', null);
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` date DEFAULT NULL COMMENT '生日',
`sex` char(1) DEFAULT NULL COMMENT '性别',
`address` varchar(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
INSERT INTO `user` VALUES ('1', '王五', null, '2', null);
INSERT INTO `user` VALUES ('10', '张三', '2014-07-10', '1', '北京市');
INSERT INTO `user` VALUES ('16', '张小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('22', '陈小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('24', '张三丰', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('25', '陈小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('26', '王五', null, null, null);
(2) 创建Java项目,引入相关jar包,编写jdbc代码。
①加载数据库驱动
②
创建并获取数据库链接
③
创建
jdbc statement
对象
④
设置
sql
语句
⑤
设置
sql
语句中的参数
(
使用
preparedStatement)
⑥
通过
statement
执行
sql
并获取结果
⑦
对
sql
执行结果进行解析处理
⑧
释放资源
(resultSet
、
preparedstatement
、
connection)
public class JdbcDemo {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
// 加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
// 通过驱动管理类获取数据库链接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis1?characterEncoding=utf-8", "root", "123456");
// 定义sql语句 ?表示占位符
String sql = "select * from user where username = ?";
// 获取预处理statement
preparedStatement = connection.prepareStatement(sql);
// 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
preparedStatement.setString(1, "王五");
// 向数据库发出sql执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
// 遍历查询结果集
while (resultSet.next()) {
System.out.println(resultSet.getString("id") + " " + resultSet.getString("username"));
}
} catch (Exception e) {
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的原始方法(未经封装)实现了查询数据库表记录的操作。
(3) jdbc问题总结如下:
① 数据库连接创建、释放频繁造成系统资源浪费,从而影响系统性能。如果使用数据库连接池可解决此问题。
②
Sql语句在代码中硬编码,造成代码不易维护,实际应用中sql变化的可能较大,sql变动需要改变java代码。
③
使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
④
对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。
3.Mybatis架构
(1) mybatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
(2) 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
(3) 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
(4) mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
(5) Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
(6) Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
(7) Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
4 mybatis下载
mybaits的代码由github.com管理
下载地址:https://github.com/mybatis/mybatis-3/releases
4.Mybatis的 HelloWorld:
(1) 创建数据表并且加入数据
create table `students` (
`StudentId` int ,
`Student_Name` varchar ,
`birth` varchar
);
(2) 加入 jar 包:
asm-3.3.1.jar
cglib-2.2.2.jar
commons-logging-1.1.1.jar
javassist-3.17.1-GA.jar
log4j-1.2.17.jar
mybatis-3.2.8.jar
mybatis-spring-1.2.2.
mysql-connector-java-5.1.7-bin.jar
(3) 创建对应的实体类
public class Student {
private Integer StudentId;
private String StudentName;
private Date
无参,有参,get set方法 toString方法......
}
(4) 加入 mybatis 的配置文件
mybatis_config.xml
:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">;
<configuration>
<!--
(了解)配置 mybatis 的环境.
1. environments 节点下可以有多个 environment 子节点.
2. default 指向某一个 environment 的 id, 以确定需要使用哪一个作为运行时环境. MYSQL或者oracle.
-->
<environments default="development">
<!--
(了解)配置具体的环境.
1. id 唯一标识当前的 environment 节点. 以被 environments 来引用.
-->
<environment id="development">
<!--
(了解)指定事务的处理类型. 取默认值即可.
-->
<transactionManager type="JDBC" />
<!--
(了解)配置数据源. type 指定使用数据源的类型.
prooperty 子节点指定连接数源的基本信息.
-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql:///mybatis" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<!-- (了解)关联多个映射文件 -->
<mappers>
<!-- (了解)关联具体的映射文件 -->
<mapper resource="com/atguigu/mybatis/helloworld/StudentMapper.xml" />
</mappers>
</configuration>
(5) 加入映射文件
StudentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-r.dtd";>;
<!--
namespace: 名称空间. 是对当前 Mapper 文件的唯一标示.
通常以 (实体类类名 + Mapper)结尾
-->
<mapper namespace="com.atguigu.mybatis.helloworld.StudentMapper">
<!--
映射一个查询语句
1. id 唯一标识改查询语句. 可以通过当前映射文件的 namespace 和 id 来唯一的定位到当前的 select.
2. resultType 指定返回值的类型. 通常为全类名.
3. 注意: 若类的属性名和数据表的列名不一致, 则可以使用别名
-->
<select id="selectStudent" resultType="com.atguigu.mybatis.helloworld.Student">
select StudentId,Student_Name AS "StudentName",birth from students where StudentId = #{id}
</select>
</mapper>
(6) 调用 mybatis 的 API 来完成查询测试
public class Main {
public static void main(String[] args) throws IOException {
//加载 mybatis 的配置文件
String resource = "mybatis_config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//利用 mybatis 的配置文件来创建 SqlSessionFactory
//SqlSessionFactory 类似于 hibernate 的 SessionFactory,用于创建 SqlSession 对象.
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取一个 SqlSession 对象.
//SqlSession 类似于 hibernate 的 Session,实际上是 mybatis 应用程序和数据库的一次会话. 实际上就是一个连接.
SqlSession session = sqlSessionFactory.openSession();
try {
//调用 SqlSession 的 selectOne 方法执行查询
//两个参数
//参数一: 利用 Mapper 文件的 namespace 和 Mapper 中的 id 唯一定位到一个 select(insert, update, delete) 节点.
//参数二: 传入 SQL 的参数
Student student = session.selectOne(
"com.atguigu.mybatis.helloworld.StudentMapper.selectStudent",2);
System.out.println(student);
} finally {
session.close();
}
}
}
5 Mybatis解决jdbc编程的问题
(1) 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。
解决:在SqlMapConfig.xml中配置数据连接池,使用连接池管理数据库链接。
(2) Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
(3) 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。
(4) 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。