MyBatis简介
- MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
- MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
- Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
传统 使用jdbc编程问题总结
jdbc编程步骤:
1、 加载数据库驱动
2、 创建并获取数据库链接
3、 创建jdbc statement对象
4、 设置sql语句
5、 设置sql语句中的参数(使用preparedStatement)
6、 通过statement执行sql并获取结果
7、 对sql执行结果进行解析处理
8、 释放资源(resultSet、preparedstatement、connection)
创建表
mysql> desc user;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(32) | NO | | NULL | |
| birthday | date | YES | | NULL | |
| sex | char(1) | YES | | NULL | |
| address | varchar(256) | YES | | NULL | |
+----------+--------------+------+-----+---------+----------------+
mysql> select * from user;
+----+---------------+------------+------+----------+
| id | username | birthday | sex | address |
+----+---------------+------------+------+----------+
| 1 | wangwu | NULL | 2 | NULL |
| 10 | zhangsan | 2014-07-10 | 1 | 北京市 |
| 16 | zhangxiaoming | NULL | 1 | 河南郑州 |
| 22 | chenxiaoming | NULL | 1 | 河南郑州 |
| 24 | zhangsanfeng | NULL | 1 | 河南郑州 |
| 25 | chenxiaoming | NULL | 1 | 河南郑州 |
| 26 | wangwu | NULL | NULL | NULL |
| 28 | wudi | NULL | 0 | USA |
| 30 | wudi1 | NULL | 0 | USA |
+----+---------------+------------+------+----------+
9 rows in set (0.00 sec)
JDBC程序
package com.mybatis.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @author CHUAN
* 原始JDBC连接代码
*/
public class jdbcConn {
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://172.16.30.189:3306/mybatis?characterEncoding=utf-8",
"root", "123");
// 定义sql语句 ?表示占位符
String sql = "select * from user where username = ?";
// 获取预处理statement
preparedStatement = connection.prepareStatement(sql);
// 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
preparedStatement.setString(1, "wangwu");
// 向数据库发出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();
}
}
}
}
}
测试结果:
1 wangwu
26 wangwu
jdbc问题总结如下:
1、 数据库连接创建、释放频繁造成系统资源浪费,从而影响系统性能。如果使用数据库连接池可解决此问题。
2、 Sql语句在代码中硬编码,造成代码不易维护,实际应用中sql变化的可能较大,sql变动需要改变java代码。
3、 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
4、 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。
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编程中对结果的解析处理过程。
Mybatis入门程序
mybatis下载
mybaits的代码由github.com管理
下载地址:https://github.com/mybatis/mybatis-3/releases
课前资料提供的mybatis如下:
- mybatis-3.2.7.jar mybatis的核心包
- lib文件夹 mybatis的依赖包所在
- mybatis-3.2.7.pdf mybatis使用手册
业务需求
使用MyBatis实现以下功能:
根据用户id查询一个用户
根据用户名称模糊查询用户列表
添加用户
更新用户
删除用户
环境搭建
- 加入jar包
加入mybatis核心包、依赖包、数据驱动包。
mybatis核心包
mybatis依赖包
数据库驱动包(已添加)
效果:
- 加入配置文件
- log4j.properties
在config下创建log4j.properties如下:# Global logging configuration log4j.rootLogger=DEBUG, stdout # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
mybatis默认使用log4j作为输出日志信息。
- SqlMapConfig.xml
在config下创建SqlMapConfig.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> <!-- 和spring整合后 environments配置将废除 --> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理 --> <transactionManager type="JDBC" /> <!-- 数据库连接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://172.16.30.189:3306/mybatis?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="123" /> </dataSource> </environment> </environments> </configuration>
SqlMapConfig.xml是mybatis核心配置文件,配置文件内容为数据源、事务管理。
- log4j.properties
- 创建pojo
pojo类作为mybatis进行sql映射使用,po类通常与数据库表对应,
数据库user表如下图:
User.java如下:
Public class User {
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
get/set……
- 第六步:sql映射文件
在config下的sqlmap目录下创建sql映射文件User.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 -->
<mapper namespace="test">
</mapper>
- 第七步:加载映射文件
mybatis框架需要加载Mapper.xml映射文件
将users.xml添加在SqlMapConfig.xml,如下:
以下按业务需求实现mybatis
- 实现根据id查询用户
使用的sql:SELECT * FROM `user` WHERE id = 1:
- 映射文件:
在user.xml中添加select标签,编写sql:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 -->
<mapper namespace="usertest">
<!-- id:statement的id 或者叫做sql的id-->
<!-- parameterType:声明输入参数的类型 -->
<!-- resultType:声明输出结果的类型,应该填写pojo的全路径 -->
<!-- #{}:输入参数的占位符,相当于jdbc的? -->
<!-- 通过ID查询一个用户 如果pojo和数据库里面的字段能一一对应上,就用resulttype自动映射-->
<select id="findUserById" parameterType="Integer" resultType="com.mybatis.pojo.User">
select * from user where id = #{v}
</select>
</mapper>
测试程序
测试程序步骤:
- 创建SqlSessionFactoryBuilder对象
- 加载SqlMapConfig.xml配置文件
- 创建SqlSessionFactory对象
- 创建SqlSession对象
- 执行SqlSession对象执行查询,获取结果User
- 打印结果
- 释放资源
myBatisDemo 程序如下:
package com.mybatis.juint;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import com.mybatis.pojo.User;
public class myBatisDemo {
@Test
public void mybatisTest() throws IOException {
// 加载核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
// 创建sqlsessionfactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(in);
// 创建sqlsession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行sql语句
User user = sqlSession.selectOne("usertest.findUserById", 10);
System.out.println(user.toString());
}
}
测试结果:
- 实现根据用户名模糊查询用户
查询sql:
SELECT * FROM `user` WHERE username LIKE ‘%wang%‘
有两种方法:
映射文件
在User.xml配置文件中添加如下内容:
<!-- #{}表示占位符 里面随便用-->
<!-- ${}字符创拼接 里面必须是value-->
<select id="findUserByUsername" parameterType="String" resultType="com.mybatis.pojo.User">
<!-- select * from user where username like ‘%${value}%‘--> ------>方法1
select * from user where username like "%"#{v}"%" ------>方法2
</select>
测试程序
@Test
public void mybatisTest2() throws IOException {
// 加载核心配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
// 创建sqlsessionfactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(in);
// 创建sqlsession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 执行sql语句
List<User> user = sqlSession.selectList("usertest.findUserByUsername",
"wu");
System.out.println(user.toString());
}
测试结果:
小结
{}和${}
- #{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
- ${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
parameterType和resultType
- parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
-
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器List中
selectOne和selectList
- selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70) - selectList可以查询一条或多条记录
- 实现添加用户
使用的sql:
INSERT INTO `user` (username,birthday,sex,address) VALUES
(‘hz‘,‘2016-07-26‘,‘1‘,‘sg‘)
映射文件:
在User.xml配置文件中添加如下内容:
<insert id="insertUser" parameterType="com.mybatis.pojo.User">
<!-- mysql 先保存数据再生成id -->
<selectKey keyProperty="id" resultType="Integer" order="AFTER">
<!-- mysql提供的LAST_INSERT_ID()函数-->
select LAST_INSERT_ID()
</selectKey>
insert into user (username,address,sex) values(#{username},#{address},#{sex})
</insert>
测试程序:
原文地址:http://blog.51cto.com/4534309/2119385