实体映射中的重复列

时间:2015-11-30 21:37:48

标签: hibernate jpa

当我坚持WorkAction时,我需要存储WorkflowInstance

的FK ID
WorkAction wa = new WorkAction();
wa.setWorkflowInstance(wfi);
waDao.persist(wa);

然而,在WorkAction fk列的表格中,workflow_instance_id最终为空。

WorkAction的实体中使用WorkflowInstance映射, insertable = false, updatable = false

@ManyToOne
@JoinColumn(name = "workflow_instance_id", referencedColumnName = "workflow_instance_id", insertable = false, updatable = false)
private WorkflowInstance workflowInstance;

当我删除它时,我得到Repeated column in mapping for entity: WorkAction column: workflow_instance_id但在WorkAction实体中我没有看到workflow_instance_id再次映射,即我没有private Long workflow_instance_id;

但后来我注意到在我的WorkAction实体中,我使用引用WorkflowInstancePlayer

的公式映射了workflow_instamce_id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumnsOrFormulas({ @JoinColumnOrFormula(formula = @JoinFormula(value = "(SELECT a.role_class_id FROM WF_WORK_ACTION_CLASS a WHERE a.work_action_class_id = work_action_class_id)", referencedColumnName = "role_class_id")),
        @JoinColumnOrFormula(column = @JoinColumn(name = "workflow_instance_id", referencedColumnName = "workflow_instance_id", insertable=false, updatable=false)) })
private WorkflowInstancePlayer player;

即使将insertable=false, updatable=false添加到该映射后,我仍然遇到问题。当我发表评论@JoinColumnsOrFormulas时,我可以移除insertable=false, updatable=false上的WorkflowInstance,而工作流_instance_id则不为空,但我会丢失WorkflowInstancePlayer

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

insertable = false, updatable = false注释中使用@JoinColumn

public class WorkAction {

   @Column(name="workflow_instance_id")
   private Long workflow_instance_id;

   @ManyToOne
   @JoinColumn(name = "workflow_instance_id", referencedColumnName = "workflow_instance_id", insertable = false, updatable = false)
   private WorkflowInstance workflowInstance;

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumnsOrFormulas({
       @JoinColumnOrFormula(formula = @JoinFormula(value = "(SELECT a.role_class_id FROM WF_WORK_ACTION_CLASS a WHERE a.work_action_class_id = work_action_class_id)", referencedColumnName = "role_class_id")),
       @JoinColumnOrFormula(column = @JoinColumn(name = "workflow_instance_id", referencedColumnName = "workflow_instance_id", insertable=false, updatable=false)) })
   private WorkflowInstancePlayer player;
}

<强>更新

我和你一样复制了同样的案例。我认为这是某种错误,因为isUpdatableisInsertable返回true。

protected void checkColumnDuplication(Set distinctColumns, Iterator columns) 
throws MappingException {
    while ( columns.hasNext() ) {
        Selectable columnOrFormula = (Selectable) columns.next();
        if ( !columnOrFormula.isFormula() ) {
            Column col = (Column) columnOrFormula;
            if ( !distinctColumns.add( col.getName() ) ) {
                throw new MappingException( 
                        "Repeated column in mapping for entity: " +
                        getEntityName() +
                        " column: " +
                        col.getName() + 
                        " (should be mapped with insert=\"false\" update=\"false\")"
                    );
            }
        }
    }
}

protected void checkPropertyColumnDuplication(Set distinctColumns, Iterator properties) 
throws MappingException {
    while ( properties.hasNext() ) {
        Property prop = (Property) properties.next();
        if ( prop.getValue() instanceof Component ) { //TODO: remove use of instanceof!
            Component component = (Component) prop.getValue();
            checkPropertyColumnDuplication( distinctColumns, component.getPropertyIterator() );
        }
        else {
            if ( prop.isUpdateable() || prop.isInsertable() ) {
                checkColumnDuplication( distinctColumns, prop.getColumnIterator() );
            }
        }
    }
}

源代码来自org.hibernate.mapping.PersistentClass

答案 1 :(得分:0)

解决方法

使用两个映射中的列名(workflow_instance_id)编译此实体的唯一方法,一个是标准的@JoinColumn,另一个是@JoinColumnOrFormula中的@JoinColumn,并且能够使用workflow_instance_id字段保留此实体填充是为了在没有公式

的WorkflowInstance映射中保持insertable = false,updatable = false
@ManyToOne
@JoinColumn(name = "workflow_instance_id", referencedColumnName = "workflow_instance_id", insertable = false, updatable = false)
private WorkflowInstance workflowInstance;

执行正常的实体经理

WorkAction wa = new WorkAction();
//wa.setWorkflowInstance(wfi); is ignored
wa.set other stuff;
waDao.persist(wa);

然后执行NativeQueryUpdate以填充workflow_instance_id列。

waDao.updateWfi(wa.getWfi_work_item_action_id(), wfi.getWorkflow_instance_id());


public void updateWfi(Long wfi_work_item_action_id, Long workflow_instance_id) {
Query query = em.createNativeQuery("UPDATE table_name SET workflow_instance_id = :workflow_instance_id WHERE wfi_work_item_action_id = :wfi_work_item_action_id");

答案 2 :(得分:0)

必须首先指定具有insertable = false和updatable = false的列,然后再指定JoinFormula。

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumnsOrFormulas({
   @JoinColumnOrFormula(column = @JoinColumn(name = "workflow_instance_id", referencedColumnName = "workflow_instance_id", insertable=false, updatable=false)),
   @JoinColumnOrFormula(formula = @JoinFormula(value = "(SELECT a.role_class_id FROM WF_WORK_ACTION_CLASS a WHERE a.work_action_class_id = work_action_class_id)", referencedColumnName = "role_class_id"))
    })
private WorkflowInstancePlayer player;

我也面临着类似的问题,现在错误消失了。