-
MyBatis框架简介
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。
MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
-
MyBatis的原理
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
-
MyBatis的基本步骤
1、 mybatis配置文件,包括Mybatis全局配置文件和Mybatis映射文件,其中全局配置文件配置了数据源、事务等信息;映射文件配置了SQL执行相关的 信息。
2、 mybatis通过读取配置文件信息(全局配置文件和映射文件),构造出SqlSessionFactory,即会话工厂。
3、 通过SqlSessionFactory,可以创建SqlSession即会话。Mybatis是通过SqlSession来操作数据库的。
4、 SqlSession本身不能直接操作数据库,它是通过底层的Executor执行器接口来操作数据库的。Executor接口有两个实现类,一个是普通执行器,一个是缓存执行器(默认)。
5、Executor执行器要处理的SQL信息是封装到一个底层对象MappedStatement中。该对象包括:SQL语句、输入参数映射信息、输出结果集映射信息。其中输入参数和输出结果的映射类型包括HashMap集合对象、POJO对象类型。
-
MyBatis的基本使用
(1)导包。
MyBatis需要一个核心包和MyBatis下载目录/lib/下的全部依赖包。因为是操作数据库,还需要使用jdbc的包。MyBatis使用的日志包是log4j的,所以需要添加log4j.properties。
在classpath下创建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
这是简单的配置。
日志级别在开发阶段设置成DEBUG,在生产阶段设置成INFO或者ERROR。
(2)创建PO(model)类,根据数据表的字段进行创建。
public class Province implements Serializable { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Province{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
(3)在classpath下,创建全局配置文件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> <!-- 配置mybatis的环境信息 --> <environments default="development"> <environment id="development"> <!-- 配置JDBC事务控制,由mybatis进行管理 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源,采用dbcp连接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="xxx"/> </dataSource> </environment> </environments> </configuration>
(4)在classpath下,创建sqlmap文件夹。在sqlmap目录下,编写映射文件。
<?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"> <mapper namespace="test"> <select id="findProvinceById" parameterType="int" resultType="com.chichung.model.Province"> select * from tb_province where id = #{id} </select> </mapper>
(5)在全局配置文件中加载映射文件
<?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的环境信息 --> <environments default="development"> <environment id="development"> <!-- 配置JDBC事务控制,由mybatis进行管理 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源,采用dbcp连接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="xxx"/> </dataSource> </environment> </environments> <mappers> <mapper resource="sqlmap/Province.xml"></mapper> </mappers> </configuration>
(6)测试:
package com.chichung; import com.chichung.model.Province; 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 java.io.IOException; import java.io.InputStream; public class Test1 { public static void main(String[] args) throws IOException { // 读取配置文件 InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml"); // 通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); // 通过SqlSessionFactory创建SqlSession SqlSession session = sqlSessionFactory.openSession(); // 调用SqlSession的操作数据库方法 Province province = session.selectOne("findProvinceById", 1); System.out.println(province); // 关闭session session.close(); } }
上面的案例可以应用于dao层。但是实际开发中并不是这样子写。实际开发中会采用mapper代理方式来实现。在这之前,需要懂得怎么使用MyBatis即可。
-
更多案例
(1)模糊查询
<!-- [${}]:表示拼接SQL字符串 [${value}]:表示要拼接的是简单类型参数。 注意: 1、如果参数为简单类型时,${}里面的参数名称必须为value 2、${}会引起SQL注入,一般情况下不推荐使用。但是有些场景必须使用${},比如order by ${colname} --> <select id="findUserByName" parameterType="String" resultType="com.gyf.domain.User"> SELECT * FROM USER WHERE username like '%${value}%' </select>
(2)插入一个新的用户
(3)删除用户
(5)更新用户的信息
(6)主键返回
有时候我们新增一条记录后,想要返回这条记录的id是多少,就可以用到自增主键。
- MySQL自增主键,是指在insert之前MySQL会自动生成一个自增的主键。
- 我们可以通过MySQL的函数获取到刚插入的自增主键:LAST_INSERT_ID()
- 这个函数是在insert语句之后去调用。
<insert id="insertUser" parameterType="com.gyf.domain.User"> <!-- [selectKey标签]:通过select查询来生成主键 [keyProperty]:指定存放生成主键的属性 [resultType]:生成主键所对应的Java类型 [order]:指定该查询主键SQL语句的执行顺序,相对于insert语句 [last_insert_id]:MySQL的函数,要配合insert语句一起使用 --> <selectKey keyProperty="id" resultType="int" order="AFTER"> SELECT LAST_INSERT_ID() </selectKey> <!-- 如果主键的值是通过MySQL自增机制生成的,那么我们此处不需要再显示的给ID赋值 --> INSERT INTO USER (username,sex,birthday,address) VALUES(#{username},#{sex},#{birthday},#{address}) </insert>
-
MyBatis需要注意的点
(1)#{ } 与 ${ }
#{}:相当于预处理中的占位符?。
#{}里面的参数表示接收java输入参数的名称。
#{}可以接受HashMap、POJO类型的参数。
当接受简单类型的参数时,#{}里面可以是value,也可以是其他。
#{}可以防止SQL注入。
${}:相当于拼接SQL串,对传入的值不做任何解释的原样输出。
${}会引起SQL注入,所以要谨慎使用。
${}可以接受HashMap、POJO类型的参数。
当接受简单类型的参数时,${}里面只能是value。
(2)selectOne 与 selectList
selectOne:只能查询0或1条记录,大于1条记录的话,会报错:
selectList:可以查询0或N条记录
-
重点:MyBatis的dao编写(mapper代理方式实现)
Mapper代理的开发方式,程序员只需要编写mapper接口(相当于dao接口)即可。Mybatis会自动的为mapper接口生成动态代理实现类。
不过要实现mapper代理的开发方式,需要遵循一些开发规范。
- mapper接口的全限定名要和mapper映射文件的namespace的值相同。
- mapper接口的方法名称要和mapper映射文件中的statement的id相同;
- mapper接口的方法参数只能有一个,且类型要和mapper映射文件中statement的parameterType的值保持一致。
- mapper接口的返回值类型要和mapper映射文件中statement的resultType值或resultMap中的type值保持一致;
(1)总体目录结构:(dao目录改为了mapper)
(2)model/Province编写PO类
public class Province implements Serializable { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Province{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
(3)mapper/ProvinceMapper编写dao接口
public interface ProvinceMapper { public abstract Province findProvinceById(int id); }
(4)mapper/ProvinceMapper.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"> <mapper namespace="com.chichung.mapper.ProvinceMapper"> <select id="findProvinceById" parameterType="int" resultType="com.chichung.model.Province"> select * from tb_province where id = #{id} </select> </mapper>
(5)MyBatis主配置文件添加映射配置文件
<?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的环境信息 --> <environments default="development"> <environment id="development"> <!-- 配置JDBC事务控制,由mybatis进行管理 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源,采用dbcp连接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="480916"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/chichung/mapper/ProvinceMapper.xml"></mapper> </mappers> </configuration>
(6)测试
public class Test1 { @Test public void test1() throws IOException { InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); SqlSession session = sqlSessionFactory.openSession(); // 通过session获取代理(jdk的动态代理原理) ProvinceMapper provinceMapper = session.getMapper(ProvinceMapper.class); Province province = provinceMapper.findProvinceById(1); System.out.println(province); session.close(); } }
-
全局配置文件其他配置
(1)properties数据库文件配置
在src下配置个db.properties文件
修改全局配置:
(2)settings标签的相关配置
具体配置详解:
(3)设置别名
别名是使用是为了在映射文件中,更方便的去指定参数和结果集的类型,不再用写很长的一段全限定名。
MyBatis支持的别名:
别名 | 映射的类型 |
_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 |
自定义别名:
注意:图中的批量配置别名的方式。要求mapper接口和mapper映射文件要名称相同,且放在同一个目录下!