我使用Mybatis(3.2.7版本)作为我的JAVA项目的ORM框架。
由于我是JPA的背景,我很想探索Mybatis支持的LAZYLOADING。
但我无法获得任何实质性的东西。
(我正在使用JAVA API和注释配置MYBATIS仅用于查询目的)
根据Mybatis文档: 1。 lazyLoadingEnabled:默认值= TRUE
全局启用或禁用延迟加载。启用后,所有关系都将是懒惰的 加载。通过使用 fetchType 属性,可以取代特定关系的此值 在它上面。
2。 aggressiveLazyLoading:默认值= TRUE
启用后,将在调用任何延迟属性时完全加载具有延迟加载属性的对象。否则,每个属性都按需加载。
的
使用以下属性,我尝试了以下代码:
一个。 JAVA课程:
Feedback.java
public class Feedback implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String message;
/**
* while loading Feedback, I want sender object to be lazily loaded
*/
private User sender;
private boolean seen;
// getters and setters
}
User.java
public class User implements Serializable, {
private static final long serialVersionUID = 1L;
private int id;
private String email;
// getters and setters
}
湾数据库架构:
反馈表
Table "public.feedback"
Column | Type | Modifiers
-------------+-----------+-------------------------------------------------------
id | integer | PRIMARY KEY
seen | boolean | not null
sender_id | integer | FOREIGN KEY (sender_id) REFERENCES users(id)
message | text |
用户表:
Table "public.users"
Column | Type | Modifiers
-------------+----------+----------------------------------------------------
id | integer | PRIMARY KEY
email | text |
℃。通过JAVA API配置MyBatis:
DataSource dataSource = new PGSimpleDataSource();
((PGSimpleDataSource) dataSource).setServerName("localhost");
((PGSimpleDataSource) dataSource).setDatabaseName(dbName);
((PGSimpleDataSource) dataSource).setPortNumber(5432);
((PGSimpleDataSource) dataSource).setUser(new UnixSystem().getUsername());
((PGSimpleDataSource) dataSource).setPassword("");
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment(dbName, transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(FeedbackMapper.class);
//
configuration.setAggressiveLazyLoading(false);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
d。在Feedbackmapper中查询DB和DB查询:
d.1 Feedbackmapper中的代码:
@Select("SELECT f.id, f.message, f.seen, f.sender_id FROM feedback f WHERE f.id= #{feedbackId}")
@Results(value = {
@Result(property = "id", column = "id"),
@Result(property = "sender", column = "sender_id", javaType = User.class, one = @One(select = "getUser", fetchType=FetchType.DEFAULT))
})
public Feedback getFeedback(@Param("feedbackId") int feedbackId);
@Select("SELECT id, email FROM users WHERE id=#{id}")
public User getUser(int id);
d.2:调用feedbackMapper中的查询的代码
// setup Mybatis session factory and config
Feedback feedback =feedbackMapper.getFeedback(70000);
System.out.println(feedback);
但仍然是"发件人"在查询getFeedback(id)时填充对象。我希望发送者对象不应该立即填充,但只有当我在获取的反馈对象上调用getSender()时才会填充。请帮助。
我最近的观察:
Mybatis团队确实在他们的文档中出错,即在文档中:
lazyLoadingEnabled:默认值= TRUE
aggressiveLazyLoading:默认值= TRUE
但是看看他们的源代码:
protected boolean lazyLoadingEnabled = false;
protected boolean aggressiveLazyLoading = true;
**但是,如果要更正,结果不会受到影响,延迟加载也无法正常工作:( **
答案 0 :(得分:7)
我想我找到了一种启用延迟加载的方法(尽管不是百分之百确定):
设置:lazyLoadTriggerMethods
描述:指定哪个Object的方法触发延迟加载
有效值:以逗号分隔的方法名称列表
默认值:equals,clone,hashCode,toString
根据源代码,此内容可正确映射到文档中的内容:
public class Configuration {
// other attributes + methods
protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(Arrays.asList(new
String[] { "equals", "clone", "hashCode", "toString" }));
}
我已将Mybatis配置更改为:
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment(dbName, transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
/**
*This is the cause why LAZY LOADING is working now
*/
configuration.getLazyLoadTriggerMethods().clear();
///////////////////////////////////////////////////
configuration.setLazyLoadingEnabled(true);
configuration.setAggressiveLazyLoading(false);
Mapper中的查询(大部分未更改):
@Select("SELECT id, message, seen, sender_id
FROM feedback WHERE f.id= #{feedbackId}")
@Results(value = {
@Result(property = "id", column = "id"),
@Result(property = "sender", column = "sender_id", javaType = User.class, one = @One(select = "getUser"))
// Set fetchType as DEFAULT or LAZY or don't set at all-- lazy loading takes place
// Set fetchType as EAGER --sender Object is loaded immediately
})
public Feedback getFeedback(@Param("feedbackId") int feedbackId);
@Select("SELECT id, email FROM users WHERE id=#{id}")
public User getUser(int id);
- 调用映射器的JAVA代码
FeedbackMapper mapper = sqlSession.getMapper(FeedbackMapper.class);
Feedback feedback =mapper.getFeedback(69999);
System.out.println("1. Feedback object before sender lazily load: \n"+ feedback);
System.out.println("2. Sender loaded explicitly \n" +feedback.getSender());
System.out.println("3. Feedback object after sender loading \n" + feedback);
1.发送者延迟加载之前的反馈对象:
{id : 69999, message : message123, sender : null, seen : false}
2. Sender loaded explicitly
{id : 65538 , email: hemant@gmail.com}
3. Feedback object after sender loading:
{id : 69999, message : message123, sender : {id : 65538, email : hemant@gmail.com},
seen : false}
的
configuration.getLazyLoadTriggerMethods().clear();
然而,由于缺乏Mybatis的文档,我不确定,这是否与任何缺点有关。
答案 1 :(得分:4)
<强>更新强>
我查看了源代码,问题是Configuration类没有反映doc。
在配置类中,默认情况下禁用延迟加载。这在提交f8ddba364092d819f100e0e8f7dec677c777d588中已更改,但文档未更新以反映更改。
protected boolean lazyLoadingEnabled = false;
我填写了错误报告https://github.com/mybatis/mybatis-3/issues/214。
现在,添加configuration.setLazyLoadingEnabled(true)以启用延迟加载。
老答案:
文档不正确。当aggressiveLazyLoading为true时,在对象上的任何方法调用之后加载所有惰性属性。 因此,调用feedback.toString()将获取反馈的发件人属性。
您应该将aggressiveLazyLoading设置为false以实现您想要的效果。
答案 2 :(得分:0)
我认为使用print
来验证mybatis中的延迟加载并不容易。
我们可以使用configuration.getLazyLoadTriggerMethods().clear();
删除默认的triggerMethods作为上一个答案。但是当我们打印它或使用toString
时,它仍然会调用getXXX
。因此它仍然会触发延迟加载以选择更多内容。因此,我们无法调试或打印以查看延迟加载的过程。
我找到了一种验证此功能的方法。
log.info("user :{}", userLazyDepartment);
log.info("user :{}", userLazyDepartment.getDepartment());