【1】mybatis在底层通过动态代理创建持久层对应的实现类应该是什么样的:
    创建的实现类应该是这样的:

    1. public class UserMapperImpl implements UserMapper {
    2. private SqlSession sqlSession;
    3. public UserMapperImpl(SqlSession sqlSession) {
    4. this.sqlSession = sqlSession;
    5. }
    6. /**
    7. * 查询所有的用户数据
    8. * @return
    9. */
    10. public List<User> getUserList() {
    11. //读取mapper文件,根据全局标识来映射到对应的sql
    12. List<User> userList = sqlSession.selectList("com.ygkj.mapper.UserMapper.getUserList");
    13. return userList;
    14. }
    15. }

    此时测试类中就不需要动态代理了,而是直接创建实现类对象,进行查询
    image.png
    更改为:
    image.png
    【2】sqlSession.getMapper是怎么代理的?
    getMapper方法底层有个代理工厂类:MapperProxyFactory.class
    其中参数为mapperProxy的newInstance方法中,Proxy.newProxyInstance的第二个参数应该是目标类实现的接口,由于其本身就是接口,所以采用new Class[]{this.mapperInterface}的写法。mybatis底层是为接口做代理,所以目标类就是接口本身。
    image.png
    对代理过程进行模拟:

    1. /**
    2. * 返回值是代理对象:为持久层接口做代理
    3. */
    4. public Object getProxy(){
    5. return Proxy.newProxyInstance(UserMapper.class.getClassLoader(), new Class[]{UserMapper.class}, new InvocationHandler() {
    6. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    7. //调用目标方法,接口没有实例,但接口可以创建匿名内部类对象
    8. Object invoke = method.invoke(new UserMapper() {
    9. //在这个方法中需要用sqlSession去xml中映射sql语句
    10. public List<User> getUserList() {
    11. //读取mapper文件,根据全局标识来映射到对应的sql
    12. List<User> userList = sqlSession.selectList("com.jy.mapper.UserMapper.getUserList");
    13. return userList;
    14. }
    15. }, args);
    16. return invoke;
    17. }
    18. });
    19. }

    【3】用mybatis对表进行增删改查需注意的点
    (1)表中字段名与实体类属性名不一致如何解决?例如表中字段名为e_name,属性名遵循驼峰命名法命名为eName,此时如何解决?
    解决方案一(不推荐):在sql语句中给字段名起别名,例如查询表中所有数据select eid,e_name as eName ,age from test04,缺点是其他不需要起别名的字段也要写出来。
    解决方案二:通过mybatis提供的resultMap标签给表中字段和实体属性建立映射关系。
    resultMap :建立起实体字段和表字段的对应关系

    1. <resultMap id="empVo" type="com.jy.pojo.Emp">
    2. <!--匹配主键字段-->
    3. <id property="eid" column="eid"></id>
    4. <!--匹配非主键字段-->
    5. <result property="eName" column="e_name"></result>
    6. <result property="age" column="age"></result>
    7. <result property="sex" column="sex"></result>
    8. <result property="salary" column="salary"></result>
    9. <result property="birthday" column="birthday"></result>
    10. </resultMap>

    此时映射关系已经建立,在select标签中就不写resultType,而是写resultMap标签及其全局标识id
    image.png
    (2)使用的方法有参数时,使用parameterType,即参数类型,如果是基本数据类型,则是什么就些什么,如果是引用数据类型,且是java.lang包中数据类型,可以直接写类名,例如String,可以写java.lang.String,也可以写String/string,甚至可以写sTring等,其他类型则为参数的全类名。

    image.png
    OGM表达式:#{} 可以取到实体中某一个字段的值,在执行sql的时候,可以防止sql注入
    PS:执行增删改操作时,需要提交事务

    1. /**
    2. * @After 会在所有的测试单元执行之后执行
    3. */
    4. @After
    5. public void mybatisAfter(){
    6. sqlSession.commit();
    7. try {
    8. resourceAsStream.close();
    9. sqlSession.close();
    10. } catch (IOException e) {
    11. e.printStackTrace();
    12. }
    13. }

    (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表达式花括号中值可以任意写。
    image.png
    image.png
    方式二:使用支持字符串拼接的el表达式,但表达式内容必须是value
    image.png
    image.png