文章目录
1. 什么是MyBatis
MyBatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。MyBatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由MyBatis框架执行sql并将结果映射为java对象并返回。
采用ORM思想解决了实体和数据库映射的问题,对jdbc进行了封装,屏蔽了jdbc api底层访问细节,使我们不用与jdbc api打交道,就可以完成对数据库的持久化操作。
2. MyBatis快速入门
2.1 创建表结构
CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` datetime default NULL COMMENT '生日',
`sex` char(1) default NULL COMMENT '性别',
`address` varchar(256) default NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.2 编写实体类
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
// 省略 get和 set方法
}
2.3 编写持久层接口
public interface IUserDao {
List<User> findAll();
}
2.4 编写持久层接口的映射文件
要求:创建位置必须和持久层接口在相同的包中,名称必须以持久层接口名称命名文件名,扩展名为.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.joker.dao.IUserDao">
<!-- 配置查询所有操作 -->
<select id="findAll" resultType="com.joker.domain.User">
select * from user
</select>
</mapper>
2.5 编写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="mysql">
<!-- 配置 mysql的环境 -->
<environment id="mysql">
<!-- 配置事务的类型 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置连接数据库的信息:用的是数据源(连接池) -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/joker"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 告知 mybatis映射配置的位置 -->
<mappers>
<mapper resource="com/joker/dao/IUserDao.xml"/>
</mappers>
</configuration>
2.6 编写测试代码
@Test
public void demo1(){
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建 SqlSessionFactory的构建者对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//3.使用构建者创建工厂对象 SqlSessionFactory
SqlSessionFactory factory = builder.build(in);
//4.使用 SqlSessionFactory生产 SqlSession对象
SqlSession session = factory.openSession();
//5.使用 SqlSession创建 dao接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//6.使用代理对象执行查询所有方法
List<User> users = userDao.findAll();
for(User user : users) {
System.out.println(user);
}
//7.释放资源
session.close();
in.close();
}
3. 基于注解的MyBatis使用
在持久层接口中添加注解:
public interface IUserDao {
@Select("select * from user")
List<User> findAll();
}
修改MyBatis配置文件:
<!-- 告知 mybatis映射配置的位置 -->
<mappers>
<mapper class="com.joker.dao.IUserDao"/>
</mappers>
4. 持久层接口的映射文件详解
使用要求:
- 持久层接口和持久层接口的映射配置必须在相同的包下。
- 持久层映射配置中mapper标签的namespace属性取值必须是持久层接口的全路径类名。
- SQL语句的配置标签<select>,<insert>,<delete>,<update>的id属性必须和持久层接口的方法名相同。
<?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.joker.dao.IUserDao">
<select id="findAll" resultType="com.joker.domain.User">
select * from user
</select>
<!-- resultType属性:用于指定结果集的类型
parameterType属性:用于指定传入参数的类型
sql语句中使用 #{}字符:它代表占位符,用于执行语句时替换实际的数据,
具体的数据是由 #{}里面的内容决定的,由于数据类型是基本类型,所以此处可以随意写
-->
<select id="findById" resultType="com.joker.domain.User" parameterType="int">
select * from user where id = #{uid}
</select>
<!-- parameterType属性:代表参数的类型,因为我们要传入的是一个类的对象,所以类型就写类的全名称
#{}中内容的写法:由于我们保存方法的参数是一个 User对象,此处要写 User对象中的属性名称
-->
<insert id="saveUser" parameterType="com.joker.domain.User">
insert into user(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address})
</insert>
<update id="updateUser" parameterType="com.joker.domain.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
where id=#{id}
</update>
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id = #{uid}
</delete>
<select id="findTotal" resultType="int">
select count(*) from user;
</select>
</mapper>
4.1 parameterType配置参数类型
parameterType属性用于指定传入参数的类型,该属性的取值可以是基本类型,引用类型(String),还可以是实体类类型。注意:基本类型和String我们可以直接写类型名称,也可以使用包名.类名的方式(如java.lang.String)。实体类类型,目前我们只能使用全限定类名。究其原因,是因为MyBatis在加载时已经把常用的数据类型注册了别名,从而我们在使用时可以不写包名,而我们的是实体类并没有注册别名,所以必须写全限定类名。后面将会讲解如何注册实体类的别名。
接下来我们通过一个模糊查询的案例来详细说明一下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">
<mapper namespace="com.joker.dao.IUserDao">
<select id="findByName1" parameterType="String" resultType="com.joker.domain.User">
select * from user where username like #{username}
</select>
<select id="findByName2" parameterType="string" resultType="com.joker.domain.User">
select * from user where username like '%${value}%'
</select>
</mapper>
@Test
public void testFindByName1() {
List<User> users = userDao.findByName1("%王%");
for(User user : users){
System.out.println(user);
}
}
在控制台输出的执行SQL语句如下:
@Test
public void testFindByName2() {
List<User> users = userDao.findByName2("王");
for(User user : users){
System.out.println(user);
}
}
在控制台输出的执行SQL语句如下:
#{}与${}的区别:
- #{}表示一个占位符号:通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。#{}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
- ${}表示拼接sql串:通过${}可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换,${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
4.2 resultType配置结果类型
resultType属性可以指定结果集的类型,它支持基本类型和实体类类型。需要注意的是,它和parameterType一样,如果注册过类型别名的,可以直接使用别名。没有注册过的必须使用全限定类名。同时,当是实体类名称时,还有一个要求,实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装。
假如实体类中的属性名称和sql查询语句中的列名不一致,我们可以通过在sql语句对查询出来的列名使用取别名的方式解决,还可以使用resultMap标签建立查询的列名和实体类的属性名称的对应关系,从而实现封装。
<?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.joker.dao.IUserDao">
<!-- resultMap标签:建立 User实体和数据库表的对应关系
* type:指定实体类的全限定类名
* id:给定一个唯一标识,是给查询 select标签引用用的
-->
<resultMap type="com.joker.domain.User" id="userMap">
<id column="id" property="userId"/>
<result column="username" property="userName"/>
<result column="sex" property="userSex"/>
<result column="address" property="userAddress"/>
<result column="birthday" property="userBirthday"/>
</resultMap>
<select id="findAll" resultMap="userMap">
select * from user
</select>
</mapper>
5. SqlMapConfig.xml配置文件详解
自定义别名:在上面面我们讲的Mybatis支持的默认别名,我们也可以采用自定义别名方式来开发:
<typeAliases>
<!-- 单个别名定义 -->
<typeAlias alias="user" type="com.joker.domain.User"/>
<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
<package name="com.joker.domain"/>
<package name="其它包"/>
</typeAliases>
配置持久层接口的映射文件位置:
<!-- 使用相对于类路径的资源 -->
<mapper resource="com/joker/dao/IUserDao.xml" />
<!-- 使用接口的类路径,此种方法要求接口名称和映射文件名称相同,且放在同一个目录中 -->
<mapper class="com.joker.dao.UserDao"/>
<!-- 注册指定包下的所有接口,此种方法要求接口名称和映射文件名称相同,且放在同一个目录中 -->
<package name="cn.joker.mybatis.mapper"/>