如何删除实体而不加载其内容?

时间:2017-08-04 16:49:58

标签: java jpa eclipselink

我有一个带有removeById操作的服务,其目的是从存储库中删除实体。由于我不想在删除之前获取实体的内容,因此我使用getReference()而不是find()来获取实体。

名为' MyObject'的实体与名为' MySource'的实体具有@ManyToOne关联,并且获取类型设置为LAZY。 当我得到一个' MyObject'的实例的引用时我从数据库中移除了该实例,这两个实例都是“我的对象”。和' MySource'在移除实例之前先进行水合作用。

示例代码:

@Entity
public class MyObject {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @ManyToOne(fetch = FetchType.LAZY)
    private final MySource source;

    public MyObject(MySource source) {
        this.source = source;
    }

    protected MyObject() {
        this.source = null;
    }

    public long id() {
        return this.id;
    }

    public MySource source() {
        return this.source;
    }

    @Override
    public boolean equals(Object obj) {
        boolean equals = this == obj;

        if (!equals && obj instanceof MyObject) {
            MyObject other = (MyObject) obj;
            equals = other.id() == id;
        }

        return equals;
    }

    @Override
    public int hashCode() {
        return (int) id % 16;
    }

}


@Entity
public class MySource {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    public MySource(String name) {
        this.name = name;
    }

    protected MySource() {
        this.name = "";
    }

    @Column
    private final String name;

    public long id() {
        return id;
    }

    public String name() {
        return this.name;
    }

    @Override
    public boolean equals(Object obj) {
        boolean equals = this == obj;

        if (!equals && obj instanceof MySource) {
            MySource other = (MySource) obj;
            equals = other.id() == id;
        }

        return equals;
    }

    @Override
    public int hashCode() {
        return (int) id % 16;
    }

}

public void removeById(long id) {
    em.getTransaction().begin();
    MyObject myObjectRef = em.getReference(MyObject.class, id);
    em.remove(myObjectRef);
    em.getTransaction().commit();
    em.clear();
}

提交事务时,我可以看到以下查询:

  • SELECT ID,来自MYOBJECT WHERE的SOURCE_ID(ID =?)
  • SELECT ID,NAME FROM MYSOURCE WHERE(ID =?)
  • 从MYOBJECT WHERE(ID =?)
  • 删除

更令人惊讶的是,如果我在“我的对象”中将提取类型从LAZY更改为EAGER。 - > ' MYSOURCE'协会,然后我获得:

  • 从MYOBJECT WHERE(ID =?)
  • 删除

这次代理人没有水合作用。

当使用代理删除实体时,LAZY加载有什么问题?当fetch类型设置为EAGER时,为什么代理不会被水合?

我是否遗漏了某些内容,或者我在EclipseLink中遇到了一些错误?

(Java 8 SE上的EclipseLink 2.6.4 +静态编织)。

附加说明

我认为代理人太热切地补充水分。例如,像this.someAssociatedEntity = other.someAssociatedEntity这样的语句会发出一个SELECT来获取该关联实体,尽管该关联是使用LAZY提取类型注释的。

我希望只有在访问关联实体的字段时才会发生SELECT。

出于调试目的: 在“MyObject”之前删除MySource表时的堆栈跟踪实体被删除:

Error Code: 0
Call: SELECT ID, NAME FROM MYSOURCE WHERE (ID = ?)
    bind => [1]
Query: ReadObjectQuery(name="source" referenceClass=MySource )
    at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processExceptionForCommError(DatabaseAccessor.java:1620)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:676)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:560)
    at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2056)
    at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:306)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.selectOneRow(DatasourceCallQueryMechanism.java:714)
    at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectOneRowFromTable(ExpressionQueryMechanism.java:2803)
    at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectOneRow(ExpressionQueryMechanism.java:2756)
    at org.eclipse.persistence.queries.ReadObjectQuery.executeObjectLevelReadQuery(ReadObjectQuery.java:555)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1175)
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:904)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1134)
    at org.eclipse.persistence.queries.ReadObjectQuery.execute(ReadObjectQuery.java:441)
    at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1222)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1857)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1839)
    at org.eclipse.persistence.internal.indirection.QueryBasedValueHolder.instantiate(QueryBasedValueHolder.java:133)
    at org.eclipse.persistence.internal.indirection.QueryBasedValueHolder.instantiateForUnitOfWorkValueHolder(QueryBasedValueHolder.java:151)
    at org.eclipse.persistence.internal.indirection.UnitOfWorkValueHolder.instantiateImpl(UnitOfWorkValueHolder.java:160)
    at org.eclipse.persistence.internal.indirection.UnitOfWorkValueHolder.instantiate(UnitOfWorkValueHolder.java:234)
    at org.eclipse.persistence.internal.indirection.DatabaseValueHolder.getValue(DatabaseValueHolder.java:89)
    at example.MyObject._persistence_get_source(MyObject.java)
    at example.MyObject._persistence_get_source_vh(MyObject.java)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor.getAttributeValueFromObject(MethodAttributeAccessor.java:82)
    at org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor.getAttributeValueFromObject(MethodAttributeAccessor.java:61)
    at org.eclipse.persistence.mappings.DatabaseMapping.getAttributeValueFromObject(DatabaseMapping.java:657)
    at org.eclipse.persistence.mappings.ForeignReferenceMapping.getAttributeValueFromObject(ForeignReferenceMapping.java:1003)
    at org.eclipse.persistence.mappings.ObjectReferenceMapping.earlyPreDelete(ObjectReferenceMapping.java:841)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1412)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531)
    at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:278)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1169)
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:134)
    at test.Main.test(Main.java:203)
    at test.Main.main(Main.java:42)

0 个答案:

没有答案