我有一个重构的 Play 应用程序。游戏模型已被重构为它自己的 Maven 项目,因此它们可以与其他项目共享,并且正在使用 ant-run 插件来增强模型类。
模型工作正常,直到它涉及加载惰性引用(我正在使用公共字段的字段增强)。引用根本没有加载,并且正在返回一个空对象。示例代码是:
@Entity
class A extends Model {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
public int id;
@ManyToOne
public B b;
public static Finder<Integer,A> finder = new Finder<Integer,A>(Integer.class, A.class);
}
@Entity
class B extends Model {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
public int id;
public String someField;
}
....
....
A a = A.finder.by(someId); // returns the correct object
B b = a.b; // Returns a not null but empty object
System.out.println(b.someField); // someField is always null
当我尝试使用引用的对象时,该对象不为空,但似乎尚未使用数据库中的数据对其进行初始化。
甚至 B 上的 id 字段也已正确填充,但其余字段则未正确填充。
Maven 似乎正在正确地增强对象(ant-run),因为我可以通过查询等获取对象。
如果我在 Java 端指定 .fetch("b") 对象会正确返回,但以前没有必要,有时也不可能这样做(在 Scala 模板中)。
我已经检查了数据库并且相关的对象在那里。代码在 Play 项目中时也可以工作,但是自从我将模型移到 Play 之外后,很多代码(不是全部)都停止了这样做。
application.conf 是否有任何特定的配置来指定延迟加载或者我错过了什么?
编辑:
我已经向 Maven 项目添加了一个测试,并使用 EBean 直接测试了这些类,而不是使用 Play 中的 Model 类,它也不起作用,所以它似乎指向 Avaje Enorm:
List<A> aS = server.find(A.class).findList();
for (A a : aS) {
B b = a.b;
System.out.println("Prop: " + a.b.someProperty); // prints Prop: null
b.refresh();
System.out.println("Prop: " + a.b.someProperty); // prints correctly the value
}
Play 编译器会做一些特别的事情来增强类吗?我使用 ant-run-plugin 来增强类,因为我找不到使 maven-enhance-plugin 工作的方法(它找不到 Play 的 Model 类来检查增强,而 antrun 确实如此)
编辑 2 我给出了正确的 #user1664823 答案,因为它有效。但它在我的情况下不起作用的原因是因为我将这些类提取到了游戏之外以及增强的工作方式。首先,我使用直接现场访问将自己的脚开枪打死。
Ebean通过修改访问器或修改字段的访问代码来增强类,添加额外的代码来检测访问并执行延迟加载机制(尝试查看增强类的反编译版本)。关于这个主题的一些好的评论可以在http://www.avaje.org/topic-159.html看到
由于我的类从 Play 主项目进入外部 Maven 项目,并且增强是使用 ant 完成的,因此仅增强了 Maven 项目中的那些类。播放代码无法使用直接字段访问触发延迟加载机制。
我没有像 user1664823 所说的那样使用 fetch 机制(它以这种方式工作),而是将代码更改为使用 getter 和 setter,现在延迟加载可以正常工作。