在hibernate实体中自动计算字段

在hibernate实体中自动计算字段,hibernate,jpa,Hibernate,Jpa,我有用于组织的简单实体类: @javax.persistence.Entity @javax.persistence.Table(name = "organization", catalog = "public") public class Organization implements Serializable { public Organization() { } @Id @GeneratedValue(strategy= GenerationType.AU

我有用于组织的简单实体类:

@javax.persistence.Entity
@javax.persistence.Table(name = "organization", catalog = "public")
public class Organization implements Serializable {
    public Organization() {
    }

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

    @Column(name = "code")
    private String code;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="parentunit", updatable = false, insertable = false)
    private Organization parentUnitEntity;

    @Column(name = "unitpath")
    private String unitPath;

    // getters, setters, other fields and so on
}
当我添加新组织并将其持久化时,我希望使用公式自动设置字段
unitPath
parentUnitEntity.unitPath+'/'+code


如何做好这件事?我尝试了
@Formula
——但它对insert不起作用。我不想手工操作,因为我想要编写的代码对实体一无所知,只保存它(对象的数据来自另一个系统)。

@Formula
仅在从数据库检索实体时使用,因此它对您没有帮助

一种解决方案可能是使用
@org.hibernate.annotations.SQLUpdate
@org.hibernate.annotations.SQLInsert
。使用这些注释,您可以覆盖hibernate执行的insert/update语句。问题是,您还希望在更新中使用细节表(自引用表),而这些注释不够灵活,无法实现这一点

另一种解决方案是编写自定义的
UserType
来处理转换。您可以实现接口,如
CompositeUserType
DynamicParameterizedType
。此解决方案更灵活,但它不是一项简单的任务。您可以在internet上查看源代码,也可以阅读JPA Persistence with Hibernate一书来了解这一点


我建议的第三个解决方案是在数据库中使用一个代替update的触发器。此解决方案不涉及JPA,您应该在数据库中创建触发器。例如,检查一下

只需使用实体侦听器:

public class Organization implements Serializable {

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

    @Column(name = "code")
    private String code;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="parentunit", updatable = false, insertable = false)
    private Organization parentUnitEntity;

    @Column(name = "unitpath")
    private String unitPath;

    @PrePersist
    protected void setUnitPath(){
       if(parentUnitEntity != null){
           unitPath = parentUnitEntity.getUnitPath() + "/" + code;
       }
    }
}