3

我想让我的实体实现某个接口,该接口返回 id:

public interface IdentifiableEntity<T extends Comparable<T>> {
    public T getIdentifier();
}

但是,如果我这样做并且实体是延迟加载的,则getIdentifier()初始化代理(并导致单独的选择)。这是一个示例实体:

@Entity
public class AppFile implements IdentifiableEntity<Long> {

    @Id
    @GeneratedValue
    private Long id;

    public Long getIdentifier() {
        return id;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    ...

}

有没有办法告诉 Hibernate/JPAgetIdentifier()只访问众所周知的 ID 而不需要初始化代理?

我已经发现:

  1. 当我注释属性(getter)而不是所有字段时,getId()不会初始化代理。
  2. @Access(AccessType.PROPERTY)在它上面使用private Long id;将表现为 1. 不需要在属性级别上注释所有内容。

更新: 1. 和 2. 都不满足我的要求,即:

  • getIdentifier()返回没有代理初始化的id
  • 该字段id不会更改其名称(因为有很多现有的 JPQL 语句)。
4

3 回答 3

0

getId()方法来初始化代理,它只需要重定向getIdentifier()方法。

public Long getId() {
    return getIdentifier();
}
于 2012-10-19T08:19:36.403 回答
0

即使您在字段上使用注释,您也可以使用 Java 反射 API 直接访问 id 值。在这里,我使用 org.easytesting fest-reflect API(反射 API 的薄包装)来缩短代码。proxy.handler.id 下的 id 值。我的示例是一个对部门(潜在代理)有多对一的员工。在我的情况下, id(s) 总是 Long ....

public Long extractIdFromDepartment(Employee employee) {

    Long idDepartment = null;

    Department departement = employee.getDepartment();
    Boolean isNotProxy = Persistence.getPersistenceUtil().isLoaded(departement);

    if (isNotProxy) {
        // here, department is not a proxy
        // a direct access is always ok
        idDepartment = departement.getId();
    } else {
        // here department IS a proxy
        // works in all cases : with Hibernate/JPA annotations on getters or fields.
        javassist.util.proxy.MethodHandler handler = Reflection.field("handler")
                .ofType(javassist.util.proxy.MethodHandler.class).in(departement).get();
        java.io.Serializable idDep = Reflection.field("id").ofType(java.io.Serializable.class).in(handler).get();
        if (idDep instanceof Long) {
            idDepartment = (Long) idDep;
        }
    }
    return idDepartment;
}
于 2016-05-10T11:10:48.013 回答
0

好吧,4年后,但这将是解决方案:

@Entity @Access(AccessType.FIELD) 公共类 AppFile 实现 IdentifiableEntity {

@Id
@GeneratedValue
@Access(AccessType.PROPERTY)
private Long id;


   public Long getId(){
       return id; 
   }

现在调用getId()实体不会初始化它的代理。

于 2017-10-16T17:40:57.690 回答