目录
- 简介
- 特点
- 几个核心组件
- 获取SqlSessionFactory
- 一个示例.
- 配置Mapper的几种方式
- 其他数据库操作
- typeHandler类型转换器
- 映射器
- 传递参数
- 分页参数RowBounds(自带的)
- 级联(1对1, 1对多)
- 鉴别器 discriminator
- 2.5 MyBatis 缓存
1 简介
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
1.1 特点
- 需要开发者自己书写SQL代码,可以对其进行优化和改造。
- 提供了映射机制,方便开发者使用。
- 提供动态SQL功能。
- 只需要一个Mapper接口和一个XML文件就能创建映射器,进一步简化开发者工作。
1.2 几个核心组件
- SqlSessionFactory 可以认为是一个数据库连接池
- SqlSession 可以看作是一个数据库连接
1.3 获取SqlSessionFactory
配置文件
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/ssm" />
<property name="username" value="root" />
<property name="password" value="数据库连接密码" />
</dataSource>
</environment>
</environments>
<mappers>
<!-- <package name="com" /> -->
<mapper class="com.mapper.RoleMapper"/>
</mappers>
</configuration>
获取SqlSessionFactory
public class DBUtil {
private static SqlSessionFactory sqlSessionFactory;
private static final String MYBATIS_CONFIG = "mybatis-config.xml";
static {
try {
InputStream inputStream = Resources.getResourceAsStream(MYBATIS_CONFIG);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
//e.printStackTrace();
throw new ExceptionInInitializerError(e);
}
}
public static SqlSessionFactory getSqlSessionFactory() {
return sqlSessionFactory;
}
}
1.4 一个示例
1 配置文件mybatis-config.xml文件如上
2 Role.java
public class Role {
private Long id;
private String roleName;
private String note;
...
}
3 数据库中有表 t_role. 字段如Role
4 一个RoleMapper.java
import com.pojo.Role;
public interface RoleMapper {
Role getRole(Long id);
}
5 RoleMapper.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.mapper.RoleMapper">
<select id="getRole" parameterType="long" resultType="com.pojo.Role">
select * from t_role where id = #{id}
</select>
</mapper>
6 测试
public static void main(String[] args) {
SqlSessionFactory factory = DBUtil.getSqlSessionFactory();
SqlSession session = factory.openSession();
RoleMapper roleMapper = session.getMapper(RoleMapper.class);
Role role = roleMapper.getRole(1L);
System.out.println(role);
session.close();
}
7 结果
Role [id=1, roleName=null, note=note_1]
- SqlSession 默认是开启了事务的, 所以在更新(insert, update, delete)操作时,我们需要手动提交事务的 session.commit();
1.5 配置Mapper的几种方式
1 <package name=“com.mapper” />
必须保证Mapper接口 和Mapper.xml配置文件放在 这个包下:com.mapper(同一个包下)
2 <mapper class=“com.mapper.RoleMapper”/>
必须保证Mapper接口 和Mapper.xml配置文件放在同一个包下(同一个包下)
3 <mapper resource=“com/xml/RoleMapper.xml”/>
Mapper接口 和 Mapper.xml配置文件 可以放在一起, 也可以不放在一起。(可以不在一起)
1.6 其他数据库操作
1 RoleMapper
public interface RoleMapper {
Role getRole(Long id);
int deleteRole(Long id);
int insertRole(Role role);
int updateRole(Role role);
List<Role> getRoles(String roleName);
}
2 配置
<mapper namespace="com.mapper.RoleMapper">
<select id="getRole" parameterType="long" resultType="com.pojo.Role">
select id, role_name as roleName, note from t_role where id = #{id}
</select>
<select id="getRoles" parameterType="string" resultType="com.pojo.Role">
select id, role_name as roleName, note from t_role where role_name like concat('%', #{roleName}, '%')
</select>
<insert id="insertRole" parameterType="com.pojo.Role">
insert into t_role(role_name, note) values(#{roleName}, #{note})
</insert>
<delete id="deleteRole" parameterType="long">
delete from t_role where id = #{id}
</delete>
<update id="updateRole" parameterType="com.pojo.Role">
update t_role set role_name = #{roleName}, note = #{note} where id = #{id}
</update>
</mapper>
1.7 typeHandler类型转换器
类型转换器定义 java类型 与 数据库字段类型 相互转换的规则。
自定义类型转换器
@MappedJdbcTypes(JdbcType.INTEGER)
@MappedTypes(SexEnum.class)
public class SexEnumTypeHandler extends BaseTypeHandler<SexEnum>{
。。。
}
注册类型转化器
<typeHandlers>
<package name="com.typehandler"/>
</typeHandlers>
2 映射器
2.1 select元素
1 传递单个参数
1 int deleteRole(Long id); 引用时名称为 id
2 Role getRole(@Param("uid") Long id); 引用时名称为 uid
2 传递多个参数
Mapper接口
Role getRole2(@Param("id")Long id, @Param("note")String note);
Mapper配置
<select id="getRole2" resultType="com.pojo.Role">
select id, role_name as roleName, note from t_role where id = #{id}
and note = #{note}
</select>
- 上面没有配置 parameterType
3 通过Bean的方式传递多个参数
Bean
public class RoleInfo {
private Long id;
private String note;
。。。
}
Mapper
Role getRole3(RoleInfo roleInfo);
配置
<select id="getRole3" parameterType="com.pojo.RoleInfo" resultType="com.pojo.Role">
select id, role_name as roleName, note from t_role where id = #{id}
and note = #{note}
</select>
4 混合参数
Mapper
Role getRole4(@Param("roleName")String roleName,
@Param("roleInfo")RoleInfo roleInfo);
配置
<select id="getRole4" resultType="com.pojo.Role">
select id, role_name as roleName, note from t_role where id = #{roleInfo.id}
and note = #{roleInfo.note}
and role_name = #{roleName}
</select>
2.2 分页参数RowBounds(自带的)
Mapper
List<Role> getRoles2(@Param("roleName")String roleName,
RowBounds rowBounds);
配置
<select id="getRoles2" resultType="com.pojo.Role">
select id, role_name as roleName, note from t_role
where role_name like concat('%', #{roleName}, '%')
</select>
- 可以看到配置文件中并没有出现RowBounds的信息,这是MyBatis自动识别的,以此进行分页的。
测试:
List<Role> roles = roleMapper.getRoles2("name", new RowBounds(4, 5));
2.3 级联
1 一对一级联 association
假设一个Employee 关联了一个WorkCard
EmployeeMapper
// 这个是EmployeeMapper
<association property="workCard" column="id"
select="com.mapper.WorkCardMapper.getWorkCardByEmpId">
</association>
// column="id" 就是下面select语句中选择的id
// 上面的association会使用这个id值, 去执行getWorkCardByEmpId(id),
// 以此获取到Employee关联的WorkCard
<select id="getEmployee" parameterType="long"
resultMap="Employee">
select id, real_name As realName, sex, birthday, mobile,
email, position, note
from t_employee where id = #{id}
</select>
WorkCardMapper
<mapper namespace="com.mapper.WorkCardMapper">
<select id="getWorkCardByEmpId" parameterType="long"
resultType="com.pojo.WorkCard">
SELECT id, emp_id as empId, real_name as realName, department,
mobile, position, note FROM t_work_card
where emp_id = #{empId}
</select>
</mapper>
2 一对多级联collection
<collection property="employeeTaskList" column="id"
select="com.mapper.EmployeeTaskMapper.getEmployeeTaskByEmpId">
</collection>
- 上面select和一对一中的是相同套路的。也是调用另一个Mapper中的方法
2.4 鉴别器 discriminator
<mapper namespace="com.mapper.EmployeeMapper">
<resultMap type="com.pojo.Employee" id="Employee">
<result property="sex" column="sex"
typeHandler="com.typehandler.SexEnumTypeHandler" />
<discriminator javaType="int" column="sex">
<case value="0" resultMap="FemaleEmployee"></case>
<case value="1" resultMap="MaleEmployee"></case>
</discriminator>
</resultMap>
<resultMap type="com.pojo.FemaleEmployee" id="FemaleEmployee" extends="Employee">
<association property="femaleHealthForm" column="id"
select="com.mapper.FemaleHealthFormMapper.getFemaleHealthForm"/>
</resultMap>
<resultMap type="com.pojo.MaleEmployee" id="MaleEmployee" extends="Employee">
<association property="maleHealthForm" column="id"
select="com.mapper.MaleHealthFormMapper.getMaleHealthForm"/>
</resultMap>
<select id="getEmployee" parameterType="long"
resultMap="Employee">
select id, real_name As realName, sex, birthday, mobile,
email, position, note
from t_employee where id = #{id}
</select>
</mapper>
- 若 sex = 0, 则Employee 的真实对象是FemaleEmployee
- 若 sex = 1, 则Employee 的真实对象是MaleEmployee
- 其中 FemaleEmployee和MaleEmployee 是Employee的子类
2.5 MyBatis 缓存
MyBatis 缓存, 是有一级缓存和二级缓存的
-
一级缓存: 在SqlSession上的缓存
-
二级缓存: 在SqlSessionFactory上的缓存
-
一级缓存是默认开启的, 而且POJO对象不需要可序列化。 (不同的SqlSession对象不共享缓存)
-
二级缓存需要手动开启。 开启方式: 在Mapper.xml文件中添加 <cache />
-
二级缓存会将对象存储到磁盘中。 所以对象需要可序列化。