MyBatis接口映射这个机制是通过面向接口编程,来代替传统的使用SqlSession调用
insert、select这种方式实现CRUD,MyBatis接口映射有两种实现方式,一种基于XML,另一种是基于注解。
基于XML:优点是可维护性、可拓展性高,SQL改动不需要动源代码,改配置文件即可,缺点是编写配置文件较为繁琐,需要定义大量的节点标签。
基于注解:优点是简洁,易用,开发速度快。不需要定义映射文件,缺点也显而易见,不利于改动,SQL语句的改动需要修改源代码,改动就意味着需要重新编译部署源代码。不过现在有个原则:规范大于约束。基于这个原则,改动的可能性并不大。
两种方式都有优缺点,按实际需求来决定使用哪种吧。
一。基于XML的接口映射
接口定义:
import java.util.List;
import java.util.Map;
public interface FoodMapper {
public Map<String, String> selectFoodById(String foodId);
public List<Map<String, String>> selectFoodsByName(String foodName);
public List<Map<String, String>> selectFoodsByPrice( String lowerLimit , String upperLimit);
}
核心配置文件:
这里就不贴全了,只贴映射声明:
<mappers>
<!-- 还是老样子,映射XML的全路径 -->
<mapper resource="cn/et/lesson02/exer/xml/FoodMapper.xml"/>
</mappers>
映射文件:
<?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">
<!--
接口绑定:将接口中的方法和对应的SQL进行绑定
命名空间使用映射的接口的全路径,对应的SQL声明的Id
则对应方法名。
-->
<mapper namespace="cn.et.lesson02.exer.xml.FoodMapper">
<select id="selectFoodById" resultType="java.util.Map">
select * from food where FOODID = #{param1}
</select>
<select id="selectFoodsByPrice" resultType="java.util.Map">
select * from food where PRICE between #{0} and #{1}
</select>
<select id="selectFoodsByName" resultType="java.util.Map">
select * from food where FOODNAME = #{0}
</select>
</mapper>
SQL语句如果需要参数,还是使用#{key}的方式,不过key并不是接口方法声明中的参数名了,而是参数的位置(下标),从0开始偏移。不过这些参数实际上是有名字的,默认是 'param1'、 'param2'...,如果现在上边的语句改成:
select * from food where PRICE between #{param1} and #{param2}
也是完全O几把K的。
如果要使用自定义的参数名,需要在方法的参数上加@Param注解:
@Param("自定义的参数名(key)")
like this:
@Param("lowerLimit") String lowerLimit ,@Param("upperLimit") String upperLimit
那么使用的时候就不能用0 1 或者 param1 param2的了,要这么写:
select * from food where PRICE between #{lowerLimit} and #{upperLimit}
这里还是用
注意:下标
测试方法:
@Test
public void selectByName() throws IOException{
FoodMapper mapper = getSession().getMapper(FoodMapper.class);
System.out.println(mapper.selectFoodsByPrice("10", "55"));
}
getSession是自己封装的一个方法,是用来获取SqlSession实例的。再通过SqlSession.getMapper,传入接口的.class,即可获取接口的实现类。这个实现类是
MyBatis自动实现的。
基于XML接口映射的原理是:
1.通过核心配置文件中的Mapper节点找到对应的Mapper.xml
2.再通过Mapper.xml命名空间中的接口全路径名获取找到该接口,创建该接口的实现类。
3.通过SQL声明的Id值找到对应的方法。这意味着接口中不能有重载,否则会报错。
其他insert、delete语句也是同理,举一反三即可。
二。基于注解的接口映射
接口:
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
public interface FoodMapper {
@Select("select * from food where FOODID = #{0}")
public Map<String, String> selectFoodById(String foodId);
@Select("select * from food where FOODNAME = #{0}")
public List<Map<String, String>> selectFoodsByName(String foodName);
@Select("select * from food where PRICE between #{0} and #{1}")
public List<Map<String, String>> selectFoodsByPrice( String lowerLimit , String upperLimit);
@Insert("insert into food values(FOOD_SEC.NEXTVAL , #{param1} , #{param2})")
public void insertFood(String foodName , String price);
}
核心配置文件:
<mappers>
<mapper class="cn.et.lesson02.exer.anno.FoodMapper"/>
</mappers>
因为基于注解实现的接口映射省去了映射文件,所以mapper节点不再使用resource属性,而是使用class属性指向映射的接口
测试:
@Test
public void selectByPrice() throws IOException{
FoodMapper mapper = getSession().getMapper(FoodMapper.class);
System.out.println(mapper.selectFoodsByPrice("10", "55"));
}