首页 > 解决方案 > Hibernate/JPA 反射问题

问题描述

我正在尝试使用 Hibernate 5.2.11.Final 从 MsSQL 数据库中的表中检索所有数据,并使用 java 反射来获取每行中字段的值。这对于 Hibernate/JPA 来说似乎很麻烦。

布局

我如何精确数据

Field field = null;
try {
    field = A.class.getDeclaredField("x");
    field.setAccessible(true);
} catch (NoSuchFieldException e) {
    e.printStackTrace();
}

CriteriaQuery<A> query = criteriaBuilder.createQuery(A.class);
Root<A> root = query.from(A.class);
query.select(root);
ScrollableResults results = session.createQuery(query).setFetchSize(100).scroll(ScrollMode.FORWARD_ONLY);

while (results.next()) {
    Object entity = results.get(0);
    log.info(entity.getClass().getSimpleName() + " " + field.get(entity))
}

这打印出来:

B test
B test2
B test3
B_$$_jvst26f_48c null
B test5

什么是 B_$$_jvst26f_48c?如果我应用“entity instanceof A”,它会返回 true - 但我无法使用反射提取它的值。如果我将实体对象转换为 A 类并使用 .getX() 提取值,则没有问题。

标签: javahibernatejpareflection

解决方案


B_$$_jvst26f_48c 是 Hibernate 生成的一个代理类,用于帮助延迟加载。

例如,假设某个实体具有对 a 的引用B,但是它B可能永远不会被访问,因此可能没有必要加载它。

该代理类将覆盖 B 的方法并添加一个测试,检查实例是否已加载,即类似(这是伪代码):

@Override
public int getX() {
    if (!proxyIsLoaded) {
        loadProxy();
    }
    return super.get();
}

这样你就可以透明地调用getX()你不需要知道它的代理。

但是,正如您所见,通过反射访问字段是行不通的。

您可以将@Proxy(lazy = false)注释添加到类,但这将禁用该实体的许多延迟加载情况


推荐阅读