使用MyBatis 3和Java进行延迟加载
我正在使用Mybatis(3.2.7版本)作为JAVA项目的ORM框架。 由于我有JPA的背景,我热衷于探索Mybatis支持的懒散加载。 但我无法理解任何实质性的东西。使用MyBatis 3和Java进行延迟加载,java,sql,mybatis,Java,Sql,Mybatis,我正在使用Mybatis(3.2.7版本)作为JAVA项目的ORM框架。 由于我有JPA的背景,我热衷于探索Mybatis支持的懒散加载。 但我无法理解任何实质性的东西。 (我正在使用JAVA API和注释配置MYBATIS,仅用于查询目的) 根据Mybatis文件: 1.lazyLoadingEnabled:默认值=真 全局启用或禁用延迟加载。启用时,所有关系都将被延迟处理 加载。对于特定关系,可以使用fetchType属性替换此值 在上面。 二,。侵略性延迟加载:默认值=真 启用时,具有延迟
(我正在使用JAVA API和注释配置MYBATIS,仅用于查询目的) 根据Mybatis文件: 1.lazyLoadingEnabled:默认值=真 全局启用或禁用延迟加载。启用时,所有关系都将被延迟处理 加载。对于特定关系,可以使用fetchType属性替换此值 在上面。 二,。侵略性延迟加载:默认值=真 启用时,具有延迟加载属性的对象将在调用任何延迟属性时完全加载。否则,将根据需要加载每个属性 使用以下属性,我尝试了以下代码: a。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
}
b。数据库模式:
反馈表
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 |
c。通过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。在反馈映射器中查询数据库和数据库查询:
@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、 反馈映射器中的1个代码:
@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)时填充“sender”对象。我希望不应立即填充sender对象,而应仅在对获取的反馈对象调用getSender()时填充。请帮忙
我最近的观察:
Mybatis团队在其文档中确实犯了错误,即在文档中:
protected boolean lazyLoadingEnabled = false;
protected boolean aggressiveLazyLoading = true;
**但是,经过纠正后,结果不会受到影响,并且延迟加载不起作用:(**更新 我查看了源代码,问题是配置类没有反映文档 在配置类中,默认情况下禁用延迟加载。这在提交中已更改,但未更新文档以反映更改
protected boolean lazyLoadingEnabled = false;
我填写了一份错误报告
现在,添加configuration.setLazyLoadingEnabled(true)以启用延迟加载
旧答案: 文档不正确。如果aggressiveLazyLoading为true,则在对对象进行任何方法调用后都会加载所有惰性属性。 因此,调用feedback.toString()将获取反馈的sender属性
您应该将aggressiveLazyLoading设置为false以实现您想要的功能。我想我找到了一种方法来启用lazyloading(尽管不确定):
- MyBatis文档在配置中具有以下设置:
- 根据源代码,这件事正确地映射到文档中给出的内容:
- Mapper中的查询(大部分未更改):
- 代码的输出
{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中缺乏文档,我不确定这是否与任何缺陷有关。
我认为使用
打印来验证mybatis中的延迟加载并不容易。
我们可以使用configuration.getLazyLoadTriggerMethods().clear();
删除默认的triggerMethods作为前面的答案。但是当我们打印它,或者使用toString
时,它仍然会调用getXXX
。因此它仍然会触发延迟加载以选择更多。因此我们无法调试或打印以查看延迟加载的过程
我找到了一种方法来验证这个函数
将日志级别设置为调试
编写以下代码并查看控制台
//configuration.setAggressiveLazyLoading(false);sqlSessionFactory=new SqlSessionFactoryBuilder().build(配置);SIR在我的配置设置中已经完成了:(我错误地认为您使用了积极的延迟加载。默认的FetchType可能不正确,并且不反映实际配置。将FetchType设置为lazy应该是目前的一种解决方法。最初是FetchType.lazy,但没有用:(我更新了答案,因为默认情况下禁用了延迟加载。请尝试通过调用configuration.setLazyLoadingEnabled(true)来启用它)。文档将很快更新。是的,你是对的。Mybatis团队在文档中确实犯了错误,即文档:1.lazyLoadingEnabled:default value=TRUE
2.aggressiveLazyLoading:default value=TRUE
但查看他们的源代码:受保护的布尔值lazyLoadingEnabled=false;
protected boolean aggressiveLazyLoading=true;
**但是,经过更正后,结果不会受到影响,并且延迟加载不起作用:(**
@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);
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);
{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}
log.info("user :{}", userLazyDepartment);
log.info("user :{}", userLazyDepartment.getDepartment());