MyBatis学习笔记(5)

MyBatis入门之延迟加载

resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。

延迟加载:先从单表查询、需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

使用association实现延迟加载

  • mapper.xml
    需要定义两个mapper的方法对应的statement。

在查询博客的statement中使用association去延迟加载下边的satatement(博客作者,即关联的用户):

<select id="findBlogAndUser" resultMap="BlogAndUser">
        SELECT
            *
        FROM 
            tbl_blog
  select>

通过上边的blogUserId来查询关联信息:

 <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
        userId, userName
    from tbl_user
        where userId = #{userid,jdbcType=INTEGER}
  select>
  • 延迟加载resultMap
"com.icss.po.Blog" id="BlogAndUser">
    <id property="blogid" column="blogId" />
    <result property="blogtitle" column="blogTitle" />
    <result property="blogcontent" column="blogContent" />

    property="user" column="blogUserId" select="com.icss.dao.UserMapper.selectByPrimaryKey" javaType="com.icss.po.User">
        <id property="userid" column="userId"/>
        <result property="username" column="userName" />

    

  

与非延迟加载的主要区别就在association标签属性多了select和column

  • 延迟加载配置

在mybatis核心配置文件中配置:lazyLoadingEnabled、aggressiveLazyLoading

设置项 描述 允许值 允许值
lazyLoadingEnabled 全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载 true/false false
aggressiveLazyLoading 当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。 true/false true

<settings>

        <setting name="lazyLoadingEnabled" value="true"/>

        <setting name="aggressiveLazyLoading" value="false"/>

    settings>
  • 测试代码
@Test
    public void testfindBlogAndUserLoading() throws Exception{

        SqlSession sqlSession =null;

        try {

            //mybatis配置文件
            String resourse = "SqlMapConfig.xml";

            //获取配置文件流

            InputStream is = Resources.getResourceAsStream(resourse);

            //创建会话工厂
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

            //通过会话工厂获取SqlSession
            sqlSession = sqlSessionFactory.openSession();

            //获取代理对象
            BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);

            List list = blogMapper.findBlogAndUser();

            for(int i=0;iget(i);

                System.out.println("博客标题:"+blog.getBlogtitle());
                System.out.println("博客内容:"+blog.getBlogcontent());

                User user = blog.getUser();

                System.out.println("博客作者:"+user.getUsername());

            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            sqlSession.close();
        }

    }

延迟加载思考

不使用mybatis提供的association及collection中的延迟加载功能,如何实现延迟加载??

实现方法如下:

定义两个mapper方法:

  • 查询博客列表
  • 根据用户id查询用户信息

实现思路:

先去查询第一个mapper方法,获取博客信息列表;在程序中(service),按需去调用第二个mapper方法去查询用户信息。

总之,使用延迟加载方法,先去查询简单的sql(最好单表,也可以关联查询),再去按需要加载关联查询的其它信息。

结果

DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 552364977.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@20ec6bb1]
DEBUG [main] - ==>  Preparing: SELECT * FROM tbl_blog 
DEBUG [main] - ==> Parameters: 
DEBUG [main] - <==      Total: 1
博客标题:Mybatis入门
博客内容:Mybatis入门程序内容
DEBUG [main] - ==>  Preparing: select userId, userName from tbl_user where userId = ? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
博客作者:Mr_Li
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@20ec6bb1]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@20ec6bb1]
DEBUG [main] - Returned connection 552364977 to pool.

注意

写代码过程中发现一个异常,然后并不是我自己引起的异常,而是因为导入的mybatis包版本问题,异常代码如下:

java.lang.NullPointerException
    at com.icss.TestMybatis.testfindBlogAndUserLoading(TestMybatis.java:333)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

这是mybatis依赖包OGNL 2.6.9的一个bug,可以通过升级mybatis版本到 3.3.0及以上来解决此问题。

mybatis官方issue说明: https://github.com/mybatis/mybatis-3/issues/224

你可能感兴趣的:(javaweb,框架,java,mybatis)