【1】mybatis在底层通过动态代理创建持久层对应的实现类应该是什么样的:
创建的实现类应该是这样的:
public class UserMapperImpl implements UserMapper {private SqlSession sqlSession;public UserMapperImpl(SqlSession sqlSession) {this.sqlSession = sqlSession;}/*** 查询所有的用户数据* @return*/public List<User> getUserList() {//读取mapper文件,根据全局标识来映射到对应的sqlList<User> userList = sqlSession.selectList("com.ygkj.mapper.UserMapper.getUserList");return userList;}}
此时测试类中就不需要动态代理了,而是直接创建实现类对象,进行查询
更改为:
【2】sqlSession.getMapper是怎么代理的?
getMapper方法底层有个代理工厂类:MapperProxyFactory.class
其中参数为mapperProxy的newInstance方法中,Proxy.newProxyInstance的第二个参数应该是目标类实现的接口,由于其本身就是接口,所以采用new Class[]{this.mapperInterface}的写法。mybatis底层是为接口做代理,所以目标类就是接口本身。
对代理过程进行模拟:
/*** 返回值是代理对象:为持久层接口做代理*/public Object getProxy(){return Proxy.newProxyInstance(UserMapper.class.getClassLoader(), new Class[]{UserMapper.class}, new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//调用目标方法,接口没有实例,但接口可以创建匿名内部类对象Object invoke = method.invoke(new UserMapper() {//在这个方法中需要用sqlSession去xml中映射sql语句public List<User> getUserList() {//读取mapper文件,根据全局标识来映射到对应的sqlList<User> userList = sqlSession.selectList("com.jy.mapper.UserMapper.getUserList");return userList;}}, args);return invoke;}});}
【3】用mybatis对表进行增删改查需注意的点
(1)表中字段名与实体类属性名不一致如何解决?例如表中字段名为e_name,属性名遵循驼峰命名法命名为eName,此时如何解决?
解决方案一(不推荐):在sql语句中给字段名起别名,例如查询表中所有数据select eid,e_name as eName ,age from test04,缺点是其他不需要起别名的字段也要写出来。
解决方案二:通过mybatis提供的resultMap标签给表中字段和实体属性建立映射关系。
resultMap :建立起实体字段和表字段的对应关系
<resultMap id="empVo" type="com.jy.pojo.Emp"><!--匹配主键字段--><id property="eid" column="eid"></id><!--匹配非主键字段--><result property="eName" column="e_name"></result><result property="age" column="age"></result><result property="sex" column="sex"></result><result property="salary" column="salary"></result><result property="birthday" column="birthday"></result></resultMap>
此时映射关系已经建立,在select标签中就不写resultType,而是写resultMap标签及其全局标识id
(2)使用的方法有参数时,使用parameterType,即参数类型,如果是基本数据类型,则是什么就些什么,如果是引用数据类型,且是java.lang包中数据类型,可以直接写类名,例如String,可以写java.lang.String,也可以写String/string,甚至可以写sTring等,其他类型则为参数的全类名。

OGM表达式:#{} 可以取到实体中某一个字段的值,在执行sql的时候,可以防止sql注入
PS:执行增删改操作时,需要提交事务
/*** @After 会在所有的测试单元执行之后执行*/@Afterpublic void mybatisAfter(){sqlSession.commit();try {resourceAsStream.close();sqlSession.close();} catch (IOException e) {e.printStackTrace();}}
(3)SqlSession用途主要有两种
①. 获取对应的Mapper,让映射器通过命名空间和方法名称找到对应的SQL,发送给数据库执行后返回结果。
②. 直接使用SqlSession,通过命名信息去执行SQL返回结果,该方式是IBatis版本留下的,SqlSession通过Update、Select、Insert、Delete等方法操作。
PS:我们通常是通过Mapper来调用方法操作数据,但通过sqlSession调用delete方法进行也是可以的,如int i = sqlSession.delete("com.jy.mapper.EmpMapper.deleteEmpById", 5);因为通过Mapper映射找到对应sql执行,其底层也是使用的IBatis中SqlSession通过Update、Select、Insert、Delete等方法操作。但MyBatis更建议使用Mapper,因为这更优雅。
(4)模糊查询
方式一:OGM表达式不支持字符串拼接,所以如果使用OGM表达式,模糊查询的双%写在参数中,OGM表达式花括号中值可以任意写。

方式二:使用支持字符串拼接的el表达式,但表达式内容必须是value

