Hibernate/JPA反射问题

huangapple go评论81阅读模式
英文:

Hibernate/JPA reflection issue

问题

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

**布局**

- 类 A 是抽象的、单表类型。具有名为 "x" 的字符串变量。
- 类 B 继承自 A

**提取数据的方法**

```java
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() 提取值,那么就没有问题。


<details>
<summary>英文:</summary>

I&#39;m trying to retrieve all data from a table in an MsSQL database using Hibernate 5.2.11.Final and using java reflection to get the value of a field in each row. This seems to be troublesome for Hibernate/JPA.

**The layout**

 - Class A is abstract, single table type. Has string variable named &quot;x&quot;
 - Class B inherits from A

**How I exact the data**

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))
}


**This prints out:**

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


What is B_$$_jvst26f_48c? If I apply &quot;entity instanceof A&quot; it returns true - yet I cannot extract its value using reflection. If I cast the entity-object to class A and extract the value using .getX() then there&#39;s no issue.

</details>


# 答案1
**得分**: 2

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

例如,假设某个实体引用了一个 `B`,但可能永远不会访问该 `B`,因此可能没有必要加载它。

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

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

这样,您可以透明地调用 getX(),无需知道它是代理。

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

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

英文:

B_$$_jvst26f_48c is a proxy class generated by Hibernate to help lazy loading.

For instance assume some entity has a reference to a B, however that B might never be accessed so it might not be necessary to load it.

That proxy class will override the methods of B and add a test checking if the instance was loaded, i.e. something like (this is pseudocode):

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

This way you can transparently call getX() you don't need to know it's proxy.

However as you have seen, accessing the fields through reflection does not work.

You can add the @Proxy(lazy = false) annotation to the class but this will disable a lot of lazy loading cases for this entity

huangapple
  • 本文由 发表于 2020年10月8日 21:22:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/64263468.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定