Skip to content

Support controlling to use lazy Initialization or not on mapper scanning feature #376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
kazuki43zoo opened this issue Apr 30, 2019 · 0 comments · Fixed by #377
Closed
Assignees
Labels
enhancement Improve a feature or add a new feature
Milestone

Comments

@kazuki43zoo
Copy link
Member

kazuki43zoo commented Apr 30, 2019

Since Spring Boot 2.2(not release yet), the lazy Initialization feature will be support. For details see https://spring.io/blog/2019/03/14/lazy-initialization-in-spring-boot-2-2. When it is enabled and one-to-one or one-to-many relationship map using @One or @Many, there are cases that it does not work fine.

Known case is as follow:

@Mapper
public interface GoodsMapper {
  @Select("select * from goods where id=#{goodsId}")
  @Results({
      @Result(id = true, column = "id", property = "id"),
      @Result(column = "name", property = "name"),
      @Result(column = "vendor_id", property = "vendor",
          one = @One(select = "com.example.mybatisspringboot22demo.VendorMapper.getVendor"))
  })
  Goods getGoods(@Param("goodsId") Integer goodsId);
}
@Mapper
public interface VendorMapper {

  @Select("select * from vendor where id=#{vendorId}")
  Vendor getVendor(@Param("vendorId") String vendorId);

}
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.example.mybatisspringboot22demo.VendorMapper.getVendor
### The error may exist in com/example/mybatisspringboot22demo/GoodsMapper.java (best guess)
### The error may involve com.example.mybatisspringboot22demo.GoodsMapper.getGoods
### The error occurred while handling results
### SQL: select * from goods where id=?
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.example.mybatisspringboot22demo.VendorMapper.getVendor

	at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)
	at com.sun.proxy.$Proxy56.selectOne(Unknown Source)
	at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:166)
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:87)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:58)
	at com.sun.proxy.$Proxy58.getGoods(Unknown Source)
	at com.example.mybatisspringboot22demo.MybatisSpringBoot22DemoApplicationTests.contextLoads(MybatisSpringBoot22DemoApplicationTests.java:18)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
	at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.example.mybatisspringboot22demo.VendorMapper.getVendor
### The error may exist in com/example/mybatisspringboot22demo/GoodsMapper.java (best guess)
### The error may involve com.example.mybatisspringboot22demo.GoodsMapper.getGoods
### The error occurred while handling results
### SQL: select * from goods where id=?
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.example.mybatisspringboot22demo.VendorMapper.getVendor
	at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:149)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:76)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433)
	... 36 more
Caused by: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.example.mybatisspringboot22demo.VendorMapper.getVendor
	at org.apache.ibatis.session.Configuration$StrictMap.get(Configuration.java:946)
	at org.apache.ibatis.session.Configuration.getMappedStatement(Configuration.java:739)
	at org.apache.ibatis.session.Configuration.getMappedStatement(Configuration.java:732)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getNestedQueryMappingValue(DefaultResultSetHandler.java:743)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getPropertyMappingValue(DefaultResultSetHandler.java:465)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.applyPropertyMappings(DefaultResultSetHandler.java:441)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getRowValue(DefaultResultSetHandler.java:404)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValuesForSimpleResultMap(DefaultResultSetHandler.java:354)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValues(DefaultResultSetHandler.java:328)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSet(DefaultResultSetHandler.java:301)
	at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:194)
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:65)
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79)
	at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63)
	at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:324)
	at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109)
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:83)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147)
	... 43 more

Solutions

Add lazyInitialization option on <mybatis:scan> and @MapperScan. The default value is false(=not use lazy initialization). If developer want to use lazy initialization for mapper bean, it should be set to the true expressly.

e.g.)

<mybatis:scan base-package="org.mybatis.spring.mapper"
        lazy-initialization="${mybatis.lazy-initialization:false}" />
@MapperScan(basePackages = "org.mybatis.spring.mapper",
        lazyInitialization = "${mybatis.lazy-initialization:false}")
public class MyBatisConfig {
  // ...
}

Limitations

Description

If following feature use, cannot use lazy Initialization.

  • ref statement on @One or @Many (<association select="..."> or <collection select="...">) with other mapper statement

  • include fragment with other mapper statement (<include refid="...">)

  • ref cache with other mapper cache (<cache-ref namespace="...">)

  • ref resultMap with other mapper result map (<select resultMap="...">)

Solution for limitations

  • Specify the bean name of dependency's mapper using @DependsOn (Spring's annotation)
@Mapper
@DependsOn("vendorMapper")
public interface GoodsMapper {
  // ...
}
@kazuki43zoo kazuki43zoo changed the title Support lazy Initialization on mapper scanning feature Support prevent lazy Initialization on mapper scanning feature Apr 30, 2019
@kazuki43zoo kazuki43zoo added this to the 2.0.2 milestone Apr 30, 2019
@kazuki43zoo kazuki43zoo added the enhancement Improve a feature or add a new feature label Apr 30, 2019
@kazuki43zoo kazuki43zoo self-assigned this Apr 30, 2019
kazuki43zoo added a commit to kazuki43zoo/spring that referenced this issue Apr 30, 2019
kazuki43zoo added a commit that referenced this issue Apr 30, 2019
Support enable/disable lazy Initialization on mapper scanning feature
kazuki43zoo added a commit that referenced this issue Apr 30, 2019
kazuki43zoo added a commit that referenced this issue May 1, 2019
kazuki43zoo added a commit to mybatis/mybatis.github.io that referenced this issue May 1, 2019
@kazuki43zoo kazuki43zoo changed the title Support prevent lazy Initialization on mapper scanning feature Support controlling to use lazy Initialization or not on mapper scanning feature Jul 3, 2019
pulllock pushed a commit to pulllock/mybatis-spring that referenced this issue Oct 19, 2023
pulllock pushed a commit to pulllock/mybatis-spring that referenced this issue Oct 19, 2023
Support enable/disable lazy Initialization on mapper scanning feature
pulllock pushed a commit to pulllock/mybatis-spring that referenced this issue Oct 19, 2023
pulllock pushed a commit to pulllock/mybatis-spring that referenced this issue Oct 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Improve a feature or add a new feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant