MyBatis映射文件
MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好。
SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):
cache – 给定命名空间的缓存配置。
cache-ref – 其他命名空间缓存配置的引用。
resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
parameterMap – 已废弃!老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除,这里不会记录。
sql – 可被其他语句引用的可重用语句块。
-
insert – 映射插入语句
-
update – 映射更新语句
-
delete – 映射删除语句
-
select – 映射查询语
SQL映射文件中实现sql语句的映射
步骤:
-
首先编写接口里的函数
-
再编写配置文件里的sql映射语句
-
最后再编写调用运行函数
接口函数
public interface EmployeeMapper { public Employee getEmpById(Integer id); public void addEmp(Employee employee); public void updataEmp(Employee employee); public Integer deleteEmpById(Integer Id); }
编写配置文件中的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="dao.EmployeeMapper"> <!--查询sql--> <select id="getEmpById" resultType="dao.Employee"> select * from tbl_employee where id = #{id} </select> <!--插入函数--> <insert id="addEmp" parameterType="dao.Employee" > insert into tbl_employee(last_name,gender,email) value(#{lastName},#{gender},#{email}) </insert> <!--修改函数--> <update id="updataEmp" parameterType="dao.Employee" useGeneratedKeys="true" keyProperty="id"> update tbl_employee set last_name=#{lastName},email=#{email},gender=#{gender} where id=#{id} </update> <!--删除函数--> <delete id="deleteEmpById" parameterType="dao.Employee"> delete from tbl_employee where id=#{id} </delete> </mapper>
编写调用函数
@Test public void test4() throws IOException { SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); //获取到的sqlSession不会自动提交 SqlSession openSession = sqlSessionFactory.openSession(); EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Employee employee = new Employee(null, "wr", "wr@atguigu.com", "0"); // 增加 // mapper.addEmp(employee); // 修改 // mapper.updataEmp(employee); // 删除 // Integer integer = mapper.deleteEmpById(5); // System.out.println(integer); // 查找 // Employee empById = mapper.getEmpById(1); //2、手动提交数据 openSession.commit(); openSession.close(); }
根据MyBatis映射文件insert获取自增主键的值
说明:一般情况下我们在创建MySQL表的时候都会定义一个主键的值,有的时候是一个自增的id的整数(在插入时不需要我们进行传递的数据),MyBatis提供了一个方法,在我们使用insert的时候给我们返回插入函数的主键的值。
编写接口函数
public interface EmployeeMapper {
public void addEmp(Employee employee);
}
编写sql配置文件中的insert
/*
如果需要获取自增的主键的值就需要以下两个属性
keyProperty:查出的主键值封装给Javabean的那个属性
useGeneratedKeys设置为 true 时,表示如果插入的表id以自增列为主键,则允许 JDBC 支持自动生成主键,并可将自动生成的主键id返回。
*/
<insert id="addEmp" keyProperty="id" useGeneratedKeys="true">
insert into tbl_employee(last_name,gender,email) value(#{lastName},#{gender},#{email})
</insert>
编写运行函数
@Test
public void test4() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//获取到的sqlSession不会自动提交
SqlSession openSession = sqlSessionFactory.openSession();
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee(null, "wr", "wr@atguigu.com", "0");
// 增加
mapper.addEmp(employee);
//将封装好的id进行打印出来即可
System.out.println(employee.getId());
//2、手动提交数据
openSession.commit();
openSession.close();
}
Mybatis的参数处理
1、单个参数: mybatis不会做特殊处理,直接使用#{参数名}:取出参数值。
案例:
//接口函数
public Employee getEmpById(Integer id);
<!--
sql映射文件的sql配置
因为只传递一个参数,所以只需要使用#{参数名}这样的方式就能直接传递数据了
-->
<select id="getEmpByMap" resultType="dao.Employee">
select * from tbl_employee where id = #{id}
</select>
//运行函数
@Test
public void test2() throws IOException {
//1、获取sqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//2、使用这个工厂获取sqlSession对象
SqlSession openSession = sqlSessionFactory.openSession();
try {
//3、获取接口的实现类对象
//会为接口自动的创建一个代理对象,代理对象去执行增删改查的方法
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
//只传递一个参数
Employee empById = mapper.getEmpById(1);
System.out.println(empById);
}finally {
openSession.close();
}
}
2、多个参数: mybatis会做特殊处理。
多个参数会被封装成一个map,
- key:param1…paramN
- value:传入的值
#{}就是从map中获取指定的key的值
案例:
//接口函数
public Employee getEmpByIdAndLastName(Integer id, String lastName);
<!--
sql映射文件的sql配置
因为传递了多个参数,所以在使用的时候要记得使用param1。。。。paramN的取值方式进行取值。
-->
<select id="getEmpByIdAndLastName" resultType="dao.Employee">
select * from tbl_employee where id = #{param1} and last_name=#{param2}
</select>
//调用函数
@Test
public void test5() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//获取到的sqlSession不会自动提交
SqlSession openSession = sqlSessionFactory.openSession();
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee employee = mapper.getEmpByIdAndLastName(1, "tom");
System.out.println(employee);
openSession.close();
}
3、命名参数: 明确指定封装参数时map的key;@Param(“id”)
多个参数会被封装成一个map,
- key:使用@Param注解指定的值
- value:参数值
#{指定的key}取出对应的参数值
案例:
//接口函数
public Employee getEmpByIdAndLastName(@Param("id") Integer id, @Param("lastName") String lastName);
<!--
sql映射文件的sql配置
因为传递了多个参数,并且使用了命名参数的规则,所以可以使用#{指定的key}取出对应的参数值的方式取值
-->
<select id="getEmpByIdAndLastName" resultType="dao.Employee">
select * from tbl_employee where id = #{id} and last_name=#{lastName}
</select>
//调用函数
@Test
public void test5() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//获取到的sqlSession不会自动提交
SqlSession openSession = sqlSessionFactory.openSession();
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee employee = mapper.getEmpByIdAndLastName(1, "tom");
System.out.println(employee);
openSession.close();
}
4、POJO: 如果多个参数正好是我们业务逻辑的数据类型,我们就可以直接传入pojo;(使用对象传递的方式进行传递数据)
#{属性名}:取出传入pojo的值
案例:
//接口函数
public void updataEmp(Employee employee);
<!--
sql映射文件的sql配置
因为传递的是对象类型的数据,所以在取数据的时候就是用#{属性名}的方式进行取值
并获取到修改数据的主键值
-->
<!--修改函数-->
<update id="updataEmp" useGeneratedKeys="true" keyProperty="id">
update tbl_employee
set last_name=#{lastName},email=#{email},gender=#{gender}
where id=#{id}
</update>
@Test
public void test4() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//获取到的sqlSession不会自动提交
SqlSession openSession = sqlSessionFactory.openSession();
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee employee = new Employee(3, "wr", "wr@atguigu.com", "0");
// 修改
mapper.updataEmp(employee);
//2、手动提交数据
openSession.commit();
openSession.close();
}
5、Map: 如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,我们也可以传入map。
#{key}:取出map中对应的值
案例:
//接口函数
public Employee getEmpByMap(Map<String,Object> map);
<!--
sql映射文件的sql配置
因为传递的是一个map集合的对象,所以在获取数据的时候要使用#{key}取出map中对应的值
-->
<select id="getEmpByMap" resultType="dao.Employee">
select * from tbl_employee where id = #{id} and last_name=#{lastName}
</select>
@Test
public void test5() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
//获取到的sqlSession不会自动提交
SqlSession openSession = sqlSessionFactory.openSession();
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Map<String,Object> map=new HashMap<String, Object>();
map.put("id",1);
map.put("lastName","tom");
Employee employee = mapper.getEmpByMap(map);
System.out.println(employee);
openSession.close();
}
6、TO: 如果多个参数不是业务模型中的数据,但是经常要使用的,推荐编写一个TO(Transfer Object)数据传输对象。
Page{
int index;
int size;
}
7、拓展
public Employee getEmp(@Param("id")Integer id,String lastName);
取值:id---->#{id/param1} lastName---->#{param2}
public Employee getEmp(Integer id,@Param("e")Employee emp);
取值:id---->#{param1} lastName---->#{param2.lastName/e.lastName}
特别注意:如果是Collection(List、Set)类型或数组类型也会特殊处理。也是把传入的list或者数组封装在map中。key:Collection(collection),如果是List还可以使用这个key(list) 数组(array)
public Employee getEmpById(List<Integer> ids);
取值:取出第一个id值 #{list[0]}
参数处理#与$取值的区别#
案例:
select * from tbl_employee where id=${id} and last_name=#{lastName}
报错结果
Prepar:select * from tbl_employee where id=2 and last_name=?
区别:
- #{}:是以预编译的形势,将参数设置到sql语句中;与PreparedStatement;防止sql注入
- ${}:取出的值直接拼接在sql语句中;会有安全问题
大多数情况下,我们去参数的值都应该去使用#{};
原生jdbc不支持占位符的地方我们就可以使用${}进行取值
比如分表、排序。。;按照年份分表拆分
select * from ${year}_salary where xxx;
select * from tbl_employee order by ${f_name} ${order}
#{}: 更丰富的用法
规定参数的一些规则
javaType、jdbcType、mode(存储过程)、numericScale、resultMap、typeHandler、jdbcTypeName、expression(未来准备支持的功能)
jdbcType:通常需要在某种特定的条件下被设置:
在我们数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理。