-
mybatis需要定位到执行哪条sql语句:
- 针对注解通过Mapper.java的全限定类名加方法名定位,例如:
package com.xh.mapper; import com.xh.Admin; //接口方法必须与xml的id相同 xml代替注解作用 public interface AdminMapper { @Select("select * from admin") public List<Admin> selectAll(); } //该定位方式即为:package+类名+方法名 = com.xh.mapper.AdminMapper.selectAll
- 针对xml配置则通过namespace+标签id组成,例如:
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xh.mapper.AdminMapper"> <select id="selectOne" resultType="Admin"> select * from admin where id = #{id} </select> </mapper> <!-- 该方式定位为:namespace+标签id = com.xh.mapper.AdminMapper.selectOne -->
- 针对注解通过Mapper.java的全限定类名加方法名定位,例如:
-
mybatis需要数据库链接以及执行的sql语句内容和sql语句的返回类型:
- 数据库连接信息:
<dataSource type="POOLED"> <property name="driver" value="${driver}"></property> <property name="url" value="${url}"></property> <property name="username" value="${username}"></property> <property name="password" value="${password}"></property> </dataSource>
- 映射信息:sql语句内容+封装结果的实体类全限定类名:
@Select("select * from admin") public List<Admin> selectAll(); /* * sql语句:select * from admin * 返回结果类型:List<Admin>标明的Admin */
或者:
<select id="selectOne" resultType="Admin"> select * from admin where id = #{id} </select> <!-- sql语句:select * from admin where id = ? 补充:#{}内的值会作为预编译参数 返回值类型: resultType="Admin"标明的的Admin -->
再或者xml+注解的形式,无论哪种形式都应当能够获取sql语句及其返回结果类型。
- 数据库连接信息:
-
根据1和2即可确定执行哪条语句以及该语句内容和返回值类型:
-
mybatis需要将以上信息封装(以下代码仅供演示):
- 将sql语句和返回类型封装为Mapper类型,代码类似于:
public class Mapper{ private String sql; private String resultType; public Mapper(String sql,String resultType){ this.sql = sql; this.resultType = resultType; } }
- mybatis对sql语句的定位语句,类似于:
String site = "com.xh.mapper.AdminMapper.selectAll" //或者 String site = "com.xh.mapper.AdminMapper.selectOne"
- 将a、b封装在一起,作为一个Map:
Map<String,Mapper> container = new HashMap<String, Mapper>() //示例: Mapper mapper = new Mapper("select * from admin","com.xh.Admin"); container.put("com.xh.mapper.AdminMapper.selectAll",mapper);
- 将sql语句和返回类型封装为Mapper类型,代码类似于:
-
从上述信息亦可解释为什么使用注解+xml时,xml的namespace为什要与Mapper接口的全限定类名相同,id要与接口方法名相同:
- 通过解析xml我们完全可以获取完整map信息,即对sql的定位和sql内容以及返回类型(resultType),即:
Mapper mapper = new Mapper("select * from admin","com.xh.Admin"); container.put("com.xh.mapper.AdminMapper.selectAll",mapper);
- 我们使用注解+xml的形式为:
InputStream is = Test.class.getClassLoader().getResourceAsStream("mybatis.xml"); SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(is); SqlSession ss = ssf.openSession(); AdminMapper up = ss.getMapper(AdminMapper.class); //使用JDK动态代理获取实例 int res = up.selectAll(); ss.commit();
- 通过getMapper(AdminMapper.class)我们可获取类Mapper.java的全限定类名com.xh.mapper.AdminMapper,通过up.selectAll()我们可以执行相应的sql语句获取返回结果。
- 通过getMapper(AdminMapper.class),java会帮我们创建Mapper接口的实现类,实现流程大致为:
- 会获取接该Mapper接口的全限定类型名:com.xh.mapper.AdminMapper
- 将需要实现的方法的方法名与全限定类名拼接: com.xh.mapper.AdminMapper.selectAll
- 将获取的定位字符串与从xml获取的map的key值一 一比较,即可获取该定位对应的sql语句和sql语句返回类型的全限定类名。
- 通过上述过程JVM就知道了如何去实现接口内某个方法的功能,最终使所有方法都具有能执行sql语句的能力。最终JVM将自己创建的实现Mapper接口所有方法的类返回给我们,而我们只需要通过向上转型的方式使用Mapper接口类型的变量接收即可。
- 以上即是使用 AdminMapper up = ss.g etMapper(AdminMapper.class); 时JVM为我们做的事情,由此我们才可以使用up.selectAll()对数据库进行增删改查。
- 其实无论是单纯的xml形式、单纯的注解形式或者xml+注解的形式,mybati做的事情都是类似的,只是获取map的方式有了些许变化。
- 通过解析xml我们完全可以获取完整map信息,即对sql的定位和sql内容以及返回类型(resultType),即: