方式一:仅mapper.xml方式
mybaits的配置:
<mappers>
<mapper resource="com/yu/hotknow/mapper/UserMapper.xml"/>
</mappers>
那么mybatis会在resource的路径中查找该mapper.xml并加载。其实质意义就是根据mapper.xml中的namespace全限定名来创建mapper接口类,并动态生成实现接口的类,当你调用xml里面某个id方法,就是调用此类实现的方法和statement集合。因此无须编写mapper接口的实现。此种方式适合在代码中采用mapper接口名称硬编码的方式获取需要调用的mapper实例。
方式二:mapper.xml+mapper接口类
而在实际中,更多的是采用这种方式,优点是非硬编码,符合面向接口编程原则,另外接口类可以利用mybatis的各种注解,满足更多需求和变化,如果有很多mapper.xml,使用上述方式比较繁琐,还可以使用包扫描加载:
<mappers>
<!-- <mapper resource="com/yu/hotknow/mapper/UserMapper.xml"/> -->
<package name="com.yu.hotknow.entity"/>
<package name="com.yu.hotknow.mapper"/>
</mappers>
需要注意的是,使用该方式的话,mapper.xml中的namespace的包、xml文件所在的包必须和package配置一致,并且需要自己创建和xml同名同包的mapper接口(如UserMapper.xml,则需要有UserMapper.java这一接口才可调用)。只要有一个条件不满足,xml里面的statement就无法使用,因为该方式不会自动创建mapper接口,也就无法使用xml中的statement。如果存在特殊情况,那么只能用第一种方式了。
方式三:仅mapper接口
即是不同mapper.xml,你仍然可以单独创建并使用mapper接口,可以结合注解和sqlprovider用编程式来实现xml中的功能。
mapper.java接口的配置:
<mappers>
<mapper class="com.yu.hotknow.mapper.UserMapper"/>
</mappers>
多个接口配置通常也采用包扫描加载:
<mappers>
<!-- <mapper resource="com/yu/hotknow/mapper/UserMapper.xml"/> -->
<package name="com.yu.hotknow.entity"/>
<package name="com.yu.hotknow.mapper"/>
</mappers>
如何使用mapper接口:
1、如果想通过namespace调用xml中的sql,在mapper.xml中,<mapper namespace="com.yu.hotknow.entity.UserMapper" >是必须的,通过session.selectOne(com.yu.hotknow.entity.UserMapper.selectUser, id);找到该mapper中的sql,通常情况下,该namespace是和session.selectOne(namespace)中的是对应的,这个和配置无关,查错谨记(不一定跟mapper resource="com/yu/hotknow/mapper/UserMapper.xml“路径一致,但是新接触的时候有惯性思维,这个注意事项上面已述),建议xml、dao接口类、namespace保持一致。
2、这个namespace通常情况下应用中应当使用全限定名,即com.yu.hotknow.entity.UserMapper,因为可能存在多个同名不同包的mapper,如果确定项目中该mapper全限定名是唯一的,则应用中可以直接用UserMapper。
3、如果想通过接口调用,引用官方指南说明:
映射器是创建用来绑定映射语句的接口。映射器接口的实例是从 SqlSession 中获得的。因此从技术层面讲,映射器实例的最大作用域是和 SqlSession 相同的,因为它们都是从 SqlSession 里被请求的。尽管如此,映射器实例的最佳作用域是方法作用域。也就是说,映射器实例应该在调用它们的方法中被请求,用过之后即可废弃。并不需要显式地关闭映射器实例,尽管在整个请求作用域(request scope)保持映射器实例也不会有什么问题,但是很快你会发现,像 SqlSession 一样,在这个作用域上管理太多的资源的话会难于控制。所以要保持简单,最好把映射器放在方法作用域(method scope)内。下面的示例就展示了这个实践:
SqlSession session = sqlSessionFactory.openSession();
try {
BlogMapper mapper = session.getMapper(BlogMapper.class);
// do work
} finally {
session.close();
}
4、mapper.xml跟mapper接口一对一配对的情况下,mapper接口中定义的方法名跟xml中定义的statement的id是不能重复的,因为他们本质就是一个接口,但是在接口中可以重载方法,这个是xml无法做到的,但是也有不擅长的地方,就是复杂的sql语句在接口和sqlprovider中是很难操作的。
5、使用xml好还是接口好?这里引用官方指南的一段话:
对于简单语句来说,注解使代码显得更加简洁,然而 Java 注解对于稍微复杂的语句就会力不从心并且会显得更加混乱。因此,如果你需要做很复杂的事情,那么最好使用 XML 来映射语句。
选择何种方式以及映射语句的定义的一致性对你来说有多重要这些完全取决于你和你的团队。换句话说,永远不要拘泥于一种方式,你可以很轻松的在基于注解和 XML 的语句映射方式间自由移植和切换。