MyBatis-mapper.xml

Mybatis-mapper.xml

使用根标签mapper的namespace属性配置接口

<?xml version="1.0" encoding="UTF-8" ?>

<!--这句话是文档类型声明,用以写xml文件约束,不是根标签-->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--根标签mapper,namespace属性的值是与之对应接口的全路径名-->
<mapper namespace="com.xiaobai.mapper.EmployeeMapper">
    
</mapper>

在根标签中可以使用子标签写crud的sql语句,每一个根标签都对应着Mapper接口中的一个具体的功能方法,也对应其具体的实现

  • select标签:查找的SQL语句标签

    • id属性:对应Mapper接口的方法名
    • resultType属性:对应SQL语句的返回值类型
  • insert

    • id属性:对应Mapper接口的方法名
    • useGeneratedKeys:开启主键回显
    • keyColumn:要回显的列名
    • keyProperty:对应回显的属性名
  • update

    • id属性:对应Mapper接口的方法名
  • delete

    • id属性:对应Mapper接口的方法名

注:在mapper接口中,不能进行方法的重载,标签与方法的映射是通过方法名实现,重载是同名不同参


# 和 $ 两种占位符

#{ key }:先将 ? 赋值给此处,再将具体的值赋值给 ?

${ key }:直接进行字符串拼接

推荐使用#{ key },防止注入攻击,但#{ key }的方式只能替代参数值

${ key }的方式可以替代容器名(标签、列名、关键字),使用此方式能实现容器名的动态

在JDBC中,我们使用PreparedStatement代替Statement解决注入攻击问题


key占位符

单个参数

当传入单个简单类型时,这个key随意写,但习惯于使用参数名,保证代码规范

<select id="queryEmployeeById" resultType="com.xiaobai.pojo.Employee">
    select emp_id empId, emp_name empName , emp_salary empSalary
    from t_emp where emp_id = #{id}
</select>

<delete id="deleteById">
    delete from t_emp where emp_id = #{id}
</delete>

<select id="queryBySalary" resultType="com.xiaobai.pojo.Employee">
    select emp_id empId, emp_name empName , emp_salary empSalary
    from t_emp where emp_salary = #{salary}
</select>

实体类对象

当传入对象为实体类对象时,key写该对象的属性名

<insert id="insertEmployee">
    insert into t_emp (emp_name , emp_salary) values (#{empName},#{empSalary})
</insert>

多个参数

当传入多个简单类型时,有两个方案写key

注解指定:在形参列表中使用@param注解指定,注解的值即为key的值

List<Employee> queryByNameAndSalary(@Param("name") String name, @Param("salary") Double salary);
<select id="queryByNameAndSalary" resultType="com.xiaobai.pojo.Employee">
    select emp_id empId , emp_name empName , emp_salary empSalary
    from t_emp where emp_name = #{name} and emp_salary = #{salary}
</select>

MyBatis机制:在形参列表中的参数,从左到右依次对应arg0, arg1……

或者使用param1, param2……

List<Employee> queryByNameAndSalary(String name, Double salary);
<select id="queryByNameAndSalary" resultType="com.xiaobai.pojo.Employee">
    select emp_id empId , emp_name empName , emp_salary empSalary
    from t_emp where emp_name = #{arg0} and emp_salary = #{arg1}
</select>
<select id="queryByNameAndSalary" resultType="com.xiaobai.pojo.Employee">
    select emp_id empId , emp_name empName , emp_salary empSalary
    from t_emp where emp_name = #{param1} and emp_salary = #{param2}
</select>

map集合参数

当传入的参数为map集合时,使用map集合的key值获取参数

// Map :
// nameKey -> nameValue
// salaryKey -> salaryValue
List<Employee> queryByNameAndSalary(Map data);
<select id="queryByNameAndSalary" resultType="com.xiaobai.pojo.Employee">
    select emp_id empId , emp_name empName , emp_salary empSalary
    from t_emp where emp_name = #{nameKey} and emp_salary = #{salaryKey}
</select>

resultType属性

当使用查询SQL语句时,我们需要使用resultType属性来配置返回结果的数据类型

<select id="queryEmployeeById" resultType="com.xiaobai.pojo.Employee">
    ……
</select>
  • 类全名
  • 别名简称

MyBatis提供了72种默认的别名,这些都是我们常用的Java数据类型mybatis – MyBatis 3 | 配置

除此之外,用户可以自定义别名和使用类全名


自定义别名

在MyBatis配置文件(mybatis-config.xml)中配置别名

使用typeAlias标签为 Java 类型设置一个缩写名字

Aliases中文释义:别名

<typeAliases>
  <typeAlias alias="Employee" type="com.xiaobai.pojo.Employee"/>
</typeAliases>

也可以指定一个包名,MyBatis会将这个包下所有的类分配别名,这个别名为类名的首字母小写形式

<typeAliases>
  <package name="com.xiaobai.pojo"/>
</typeAliases>

当使用package批量管理时,可以使用注解@Alias为类起另外的名字

@Data
@Alias("em")
public class Employee {
	……
}

指定结果类型为Map

当我们返回结果是单个实体类对象但没有对应的实体类可以接值时,

我们可以使用map集合来接,key为列名,value为值

Map<String, Object> queryMaxSalaryAndAverageSalary();
<select id="queryEmployeeById" resultType="map">
    ……
</select>

指定结果类型为List

当我们返回结果是多个实体类对象,但没有对应的实体类可以接值时,我们可以使用List集合来接

注:当返回值为列表时,resultType属性只写List中的具体数据类型

这是因为底层的iBatis的查询方法有两个:selectOne和selectList

但selectOne方法的本质时调用selectList方法查询集合后取第一个

List<String> queryNamesBySalary(Double salary);
<select id="queryNamesBySalary" resultType="string">
    select emp_name
    from t_emp
    where emp_salary > #{salary}
</select>

insert标签及相关问题

事务

之前在配置文件中讲过,MyBaits会关闭自动提交(开启事务)

SqlSession sqlSession = sqlSessionFactory.openSession(true); // 在获取sqlSession时开启自动提交(关闭事务)

或者在关闭连接之前手动提交事务

sqlSession.commit(); // 手动提交事务

主键回显

主键回显就是将数据库自动增长的主键会显到实体类中,业务层可获取到这个值

在insert标签中,使用属性配置主键回显

  • useGeneratedKeys:开启主键回显
  • keyColumn:要回显的列名
  • keyProperty:对应回显的属性名
<insert id="insertEmployee" useGeneratedKeys="true" keyColumn="emp_id" keyProperty="empId">
    insert into t_emp (emp_name , emp_salary) values (#{empName},#{empSalary})
</insert>

Mybatis维护主键自增

方案一:通过Java自带的工具类UUID随机生成id值,作为用户的唯一约束也就是主键值

TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
String uuid = UUID.randomUUID().toString().replaceAll("-", " ");
mapper.insert(new Teacher(uuid,"xiaobai"));

方案二:在mapper.xml中,使用insert子标签selectKey运行sql代码

  • order属性:after|before selectKey中代码在在sql语句之前还是之后执行
  • resultType属性:返回值类型
  • keyProperty属性:给实体类中哪一个属性赋值
<insert id="insert">
    <selectKey order="BEFORE" resultType="string" keyProperty="tId">
        select replace(uuid(),"-"," ")
    </selectKey>
    insert into teacher (t_id,t_name)
    value (#{tId},#{tName})
</insert>

先通过selectKey执行uuid()再使用replace()替换"-"为" ",然后将sql执行的结果以String接收后赋值给实体类的tId属性

这样再执行insert命令时,实体类的tId属性存在一个sql生成的uuid了


列名和属性名映射

之前的学习中,我们针对属性名和别名不同的处理方式是起别名,但MyBatis为我们提供了更好的解决方式

在MyBatis配置文件(mybatis-config.xml)中配置settings项

开启mapUnderscoreToCamelCase为true,即可自动映射数据库列名和实体类属性名

<setting name="mapUnderscoreToCamelCase" value="true"/>

mapUnderscoreToCamelCase中文释义:映射下划线至驼峰

学到今天终于解决了这个问题了,开心!!! 😊


ResultMap

resultType的是按照规则自动映射,如果开启驼峰转换后,resultType也只是按照驼峰转换的规则自动映射

resultType只能映射一层结构,多表查询的结果无法自动映射!!!

所以,我们可以使用resultMap标签新建自定义映射规则

  • id属性:规则集别名
  • type:映射类型(命名方式与resultType相同,使用类全名或者 别名)
id标签

resultMap的子标签id,用来做主键列映射关系

result标签

resultMap的子标签result,用来做非主键列映射关系


在select标签中设置resultMap映射规则,值为其别名

这样就完成了利用resultMap去配置 列名和属性名映射

<resultMap id="tMap" type="com.xiaobai.pojo.Teacher">
    <id column="t_id" property="tId"/>
    <result column="t_name" property="tName"/>
</resultMap>
<select id="queryById" resultMap="tMap">
    select * from teacher where t_id = #{id}
</select>

resultMap的功能远不止如此,我们在这里只是学习他的其中一种功能