英文:
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'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 "x"
- 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 "entity instanceof A" 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'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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论