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的功能远不止如此,我们在这里只是学习他的其中一种功能