MyBatis 前身是apache的一个开源项目 iBatis , 2010 年这个项目迁移到了google code,改名为MyBatis 。2013年11月迁移到 Github 。 最新版本是Mybatis3。
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
github地址:https://github.com/mybatis/
中文帮助文档:http://www.mybatis.org/mybatis-3/zh/index.html
准备工作
创建表、实体类、Mapper(即Dao层接口),实现查询全部班级信息。
CREATE DATABASE schools;
USE schools;
CREATE TABLE clses(
cid INT(10) AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(20)
);
INSERT INTO clses VALUES(DEFAULT, 'cls1901');
INSERT INTO clses VALUES(DEFAULT, 'cls1902');
INSERT INTO clses VALUES(DEFAULT, 'cls1903');
INSERT INTO clses VALUES(DEFAULT, 'cls1904');
INSERT INTO clses VALUES(DEFAULT, 'cls1905');
INSERT INTO clses VALUES(DEFAULT, 'cls1906');
COMMIT;
SELECT * FROM clses;
一个Mapper对于一个xml映射文件,可以把映射文件想象成接口的实现类。
该映射文件需要放在classpath类路径下,一般放在mapper接口路径下。
<mapper namespace="com.bodhixu.mybatis.mapper.ClsMapper">
<select id="queryAll" resultType="com.bodhixu.mybatis.bean.Cls">
select * from clses
select>
mapper>
Mybatis全局配置文件,需要放在classpath路径下,一般新建“source folder”。
<configuration>
<environments default="default">
<environment id="default">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/schools"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
dataSource>
environment>
environments>
<mappers>
<package name="com.bodhixu.mybatis.mapper"/>
mappers>
configuration>
后期代码被Spring优化,可省略。
@Test
void testQueryAll() throws Exception {
//读取mybatis配置文件
InputStream is = getClass().getResourceAsStream("/mybatis.xml");
//创建Session工厂
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
//创建SqlSession
SqlSession session = sessionFactory.openSession();
//创建Mapper
ClsMapper mapper = session.getMapper(ClsMapper.class);
//执行数据库操作
List<Cls> clses = mapper.queryAll();
for (Cls cls : clses) {
System.out.println(cls);
}
//关闭session
session.close();
}
MyBatis 配置
SqlMapConfig.xml:mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml:sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
SqlSessionFactory
通过mybatis环境等配置信息构造SqlSessionFactory,即会话工厂。
sqlSession
由会话工厂创建sqlSession,即会话,操作数据库需要通过sqlSession进行。
Executor
mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
MappedStatement
MappedStatement 也是 mybatis 一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
输入映射
Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo。Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
输出映射
Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
准备工作:设置.properties文件格式为"UTF-8"。
操作步骤:“ Windows–>Preferences–>General–>Content Types–>Text–>Java Propertied File–>修改Defaul encoding:UTF-8 ->点Update->applay and close”
导入jar包, log4j-xx.jar
配置文件, log4j.properties,必须放在classpath类路径下,文件名不可以改变。
# 日志级别设置成ERROR,控制台输出CONSOLE,文件输出LOGFILE(如需要则添加)
log4j.rootCategory = ERROR, CONSOLE
# 对于mapper包下的logger级别设置成DEBUG
# 需要修改mapper包名
log4j.logger.com.bodhixu.mybatis.mapper = DEBUG
log4j.appender.CONSOLE = org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern = %C %d{yyyy-MM-dd HH:mm:ss} %m %n
log4j.appender.LOGFILE = org.apache.log4j.FileAppender
# 需要修改输出文件的路径
log4j.appender.LOGFILE.File = E:/my.log
log4j.appender.LOGFILE.Append = true
log4j.appender.LOGFILE.layout = org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern = %C %m %L %n
5.1 文档结构
配置文件的文档结构,必须按顺序配置
configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
5.2 properties(属性)
引入外部properties配置文件
<properties resource="db.properties">properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
dataSource>
environment>
environments>
5.3 settings(设置)
settings 运行时行为设置,比如mapUnderscoreToCamelCase,可以自动完成自动完成属性名称hotelName到数据库中字段hotel_name的映射。另外如果不符合规则映射失败,可以通过查询语句的列别名实现。
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
<select id="queryAll2" resultType="com.bodhixu.bean.Cls2">
select c_id, c_name name from clses2
select>
5.4 typeAliases(类型别名)
typeAliases,实现为java类型起别名。
别名 | 映射的类型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
map | Map |
<typeAliases>
<typeAlias type="com.bodhixu.ssm.bean.Stu" alias="Stu"/>
typeAliases>
<typeAliases>
<package name="com.bodhixu.ssm.bean"/>
typeAliases>
5.5 mappers(映射器)
mappers将sql映射映射到全局配置文件中
<mappers>
<mapper resource="com/bodhixu/ssm/mapper/StuMapper.xml"/>
mappers>
<mappers>
<mapper class="com.bodhixu.bean.Cls"/>
mappers>
<mappers>
<package name="com.bodhixu.ssm.mapper"/>
mappers>
6.1 resultType
mapper.xml中通过resultType属性设置查询操作的返回类型。如果是增、删、改操作则没有返回类型,因为都返回int,表示影响的行号。如果返回类型为集合,则resultType为集合中的泛型类型。
6.2 parameterType
mapper.xml中可以通过parameterType属性设置参数类型。
6.3 #{} 和 ${}
#{}
表示一个占位符号,可接收简单类型值或pojo属性值。如果接收简单类型值,#{}
括号中可以写value或其它名称。
Stu queryById(long sid) throws Exception;
<select id="queryById" resultType="com.bodhixu.ssm.bean.Stu" parameterType="long">
select * from stus where sid = #{sid}
select>
${}
用于sql串拼接,可以接收简单类型值或pojo属性值。如果接收简单类型值,${}
括号中只能写value。
<select id="queryById" resultType="com.bodhixu.ssm.bean.Stu" parameterType="long">
select * from stus where sid = ${value}
select>
6.4 模糊查询
模糊查询如果使用#{},传参时必须传字符串"%查询内容%",此时可以使用**’%${value}%’**,参数直接传查询内容即可。
//根据名字模糊查询
List<Stu> queryByName(String subName) throws Exception;
<select id="queryByName" resultType="stu">
select * from stus where name like '%${value}%'
select>
6.5 多个简单类型参数的处理
方式1:通过索引取值
不能使用parameterType, 改用#{index}
,是第几个参数就用第几个的索引,索引从0开始。
//查询年龄在指定范围的学生
List<Stu> queryByAge(int min, int max) throws Exception;
<select id="queryByAge" resultType="stu">
select * from stus where age between #{0} and #{1}
select>
方式2:将多参数封装成map格式的数据,通过Map的key取值
#{key}使用map中key的名字获得value值
//查询年龄在指定范围的学生
List<Stu> queryByAge2(Map<String, Integer> map) throws Exception;
<select id="queryByAge2" resultType="stu">
select * from stus where age between #{min} and #{max}
select>
@Param
传值//查询年龄在指定范围的学生
List<Stu> queryByAge3(@Param("m") int min, @Param("max") int max) throws Exception;
<select id="queryByAge3" resultType="stu">
select * from stus where age between #{m} and #{max}
select>
6.6 删除数据
void deleteById(long sid) throws Exception;
<delete id="deleteById">
delete from stus where sid = #{sid}
delete>
6.7 修改数据
void update(Stu stu) throws Exception;
update stus set sname = #{sname}, sage = #{sage} where sid = #{sid}
6.8 插入数据
void insert(Stu stu) throws Exception;
<insert id="insert" parameterType="com.bodhixu.ssm.bean.Stu">
insert into stus values(seq_stus.nextval, #{name}, #{age}, #{birthday})
insert>
//注意,默认操作未开始事务,必须手动提交
sqlSession.commit();
6.9 增删改的返回值和异常
可以返回void或者int。如果返回int,如果操作成功,返回的是受影响数据的数量。如果失败则抛出异常(如插入不允许重复的重复数据,或者删除有外键关联的数据)。
6.9 添加并返回自增主键
slectkey
标签,查询自增主键void insertGetKey(Stu stu) throws Exception;
<insert id="insertGetKey" parameterType="com.bodhixu.ssm.bean.Stu">
<selectKey keyColumn="sid" keyProperty="sid" resultType="Long" order="AFTER">
select LAST_INSERT_ID()
selectKey>
insert into stus(sname, sage, birthday) values(#{name}, #{age}, #{birthday});
insert>
<insert id="insertGetKey" parameterType="com.bodhixu.ssm.bean.Stu">
<selectKey keyColumn="sid" keyProperty="sid" resultType="long" order="BEFORE">
select stus.nextval as sid from dual
selectKey>
insert into stus values(#{sid}, #{name}, #{sage}, #{birthday});
insert>
需要在全局配置文件中设置useGeneratedKeys为true
<settings>
<setting name="useGeneratedKeys" value="true"/>
settings>
在xml映射文件中,同样设置useGeneratedKeys为true,并且指明主键名称
<insert id="insert" useGeneratedKeys="true" keyProperty="cid" keyColumn="cid" parameterType="com.bodhixu.mybatis.bean.Cls">
insert into cls(name, create_date) values(#{name}, #{createDate})
insert>