Mapper.xml继承机制
Mybatis实际上隐藏了一个功能:Mapper.xml可以继承,这个在官方文档中并没有提到过,不过在这个issue (commit)里提到过。
Statement覆盖
利用Mapper.xml的继承机制,我们可以做到ChildMapper覆盖ParentMapper中select
、insert
、delete
、update
。下面举例说明:
Interface:
@MybatisMapper public interface ParentMapper { String selectFoo(); String selectBar(); } @MybatisMapper public interface ChildMapper extends ParentMapper { String selectLoo(); }
Mapper.xml:
<mapper namespace="me.chanjar.mybatislearn.inherit.statement.ParentMapper"> <select id="selectFoo" resultType="String"> SELECT 'Foo From Parent' FROM dual </select> <select id="selectBar" resultType="String"> SELECT 'Bar From Parent' FROM dual </select> </mapper> <mapper namespace="me.chanjar.mybatislearn.inherit.statement.ChildMapper"> <!-- 覆盖 Parent.selectFoo的定义 --> <select id="selectFoo" resultType="String"> SELECT 'Foo From Child' FROM dual </select> <!-- 不覆盖 Parent.selectBar的定义 --> <!-- 自己的 Child.selectLoo的定义 --> <select id="selectLoo" resultType="String"> SELECT 'Loo From Child' FROM dual </select> </mapper>
规律可以总结为:
- ParentMapper.xml中有,ChildMapper.xml中没有,ChildMapper沿用ParentMapper.xml中的定义
- ParentMapper.xml中有,ChildMapper.xml中也有,ChildMapper使用ChildMapper.xml中的定义
- ParentMapper.xml中没有,ChildMapper.xml中有,ChildMapper使用ChildMapper.xml中的定义
ResultMap覆盖
Mapper.xml继承机制只针对statement有效,对于sql
、resultMap
是无效的。
如果要在ChildMapper.xml中覆盖这些,必须要先覆盖ParentMapper.xml中的statement,然后让这些statement使用新的sql
、resultMap
等。
下面举例一个给ITEM表添加字段,但是不修改原来的ItemMapper的例子:
Model:
public class Item { private Integer id; private String title; // setter and getter ... } public class ItemEx extends Item { private String name; // setter and getter ... }
Interface:
@MybatisMapper public interface ItemMapper { Item getById(@Param("id") Long id); } @MybatisMapper public interface ItemExMapper extends ItemMapper { }
Mapper.xml:
<mapper namespace="me.chanjar.mybatislearn.inherit.resultmap.ItemMapper"> <select id="getById" resultMap="Item"> select * from item where id = #{id} </select> <resultMap id="Item" type="me.chanjar.mybatislearn.inherit.resultmap.Item" autoMapping="true"> <id property="id" column="id" /> </resultMap> </mapper> <mapper namespace="me.chanjar.mybatislearn.inherit.resultmap.ItemExMapper"> <!-- 如果这里不写一遍,就会用到ItemMapper.getById的定义,resultMap就不会是ItemEx--> <select id="getById" resultMap="Item"> select * from item where id = #{id} </select> <resultMap id="Item" type="me.chanjar.mybatislearn.inherit.resultmap.ItemEx" autoMapping="true"> <id property="id" column="id" /> </resultMap> </mapper>