Hibernate - 属性是多对一的,同时是组件?

时间:2016-01-21 02:28:33

标签: java hibernate

我是Hibernate的新手,从MyBatis迁移。 我有这个Customer bean,我正在尝试使用xml映射保存(INSERT)。这是我的代码的较短版本:

豆类:

public class Customer {
    private Integer id;
    private String code;
    private SystemObject systemObject = new SystemObject();    
}

public class SystemObject {

    private Integer objectId; 
    private Integer userIdCreate; 
    private Integer userIdUpdate; 
    private Date createDate;
    private Date updateDate;    
    private Workspace workspace = new Workspace();    
}

public class Workspace {
    private Integer id;
    private String code;
    private String name;
}

如您所见,Customer有一个SystemObject。 SystemObject是一个通用对象,代码中的所有bean都有一个。 SystemObject有一个工作区。

问题是,表CUSTOMER,对OBJECT的引用,以及对WORKSPACE 的引用。在“objects world”中,我通过执行getSystemObject()。getWorkspace()。getId()来获取工作区id,但我不知道如何在Hibernate中执行此操作

表(目前在PostgreSQL上):

create table CUSTOMER (
   CUSTOMER_ID          INT4                 not null,
   OBJECT_ID            INT4                 not null,
   WORKSPACE_ID         INT4                 not null,
   CODE                 VARCHAR(100)         not null,
   constraint PK_CUSTOMER primary key (CUSTOMER_ID),
   constraint AK_CUS_CODE unique (WORKSPACE_ID, CODE)
);

create table OBJECT (
   OBJECT_ID            INT4                 not null,
   WORKSPACE_ID         INT4                 not null,
   USER_ID_CREATE       INT4                 not null,
   USER_ID_UPDATE       INT4                 not null,
   CREATE_DATE          DATE                 not null,
   UPDATE_DATE          DATE                 not null,
   constraint PK_OBJECT primary key (OBJECT_ID)
);

create table WORKSPACE (
   WORKSPACE_ID         INT4                 not null,
   CODE                 VARCHAR(100)         not null,
   NAME                 VARCHAR(100)         not null,
   constraint PK_WORKSPACE primary key (WORKSPACE_ID),
   constraint AK_WS_CODE unique (CODE)
);

alter table CUSTOMER
   add constraint FK_CUS_OBJ foreign key (OBJECT_ID)
      references OBJECT (OBJECT_ID)
      on delete restrict on update restrict;

alter table CUSTOMER
   add constraint FK_CUS_WS foreign key (WORKSPACE_ID)
      references WORKSPACE (WORKSPACE_ID)
      on delete restrict on update restrict;

alter table OBJECT
   add constraint FK_OBJ_WS foreign key (WORKSPACE_ID)
      references WORKSPACE (WORKSPACE_ID)
      on delete restrict on update restrict;

而且,这是我对Customer对象的映射:

<class name="ar.com.portal.bean.Customer" table="CUSTOMER">
    <id name="id" column="CUSTOMER_ID" >
        <generator class="increment"></generator>
    </id>
    <property name="code" column="CODE" />
    <many-to-one name="systemObject" class="ar.com.framework.base.SystemObject" column="OBJECT_ID" 
            unique="true" not-null="true" lazy="false" cascade="all" ></many-to-one>
</class>

主要代码:

Session session = HibernateSessionManager.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();

Customer anew = new Customer();
anew.setCode("new test");
SystemObjectManager.prepareSystemObject(anew); //this line sets all values for the systemObject inside Customer
anew.getSystemObject().getWorkspace().setId(1);
session.save(anew);
transaction.commit();

这样,hibernate尝试插入两个对象Customer和SystemObject,但是因为Customer在WORKSPACE_ID列中为null而失败:

(对不起,错误是西班牙语)

Caused by: org.postgresql.util.PSQLException: ERROR: el valor null para la columna «workspace_id» viola la restricción not null   Detail: La fila que falla contiene (3, 8, null, 'new test').

然后,我尝试了这种方式。在SystemObject中添加了一个getWorkspaceId()(只是为了尝试简化一步)并将映射更改为:

<class name="ar.com.portal.bean.Customer" table="CUSTOMER">
    <id name="id" column="CUSTOMER_ID" >
        <generator class="increment"></generator>
    </id>
    <property name="code" column="CODE" />
    <component name="systemObject" class="ar.com.framework.base.SystemObject" >
        <property name="workspaceId" column="WORKSPACE_ID" />
    </component>
    <many-to-one name="systemObject" class="ar.com.framework.base.SystemObject" column="OBJECT_ID" 
            unique="true" not-null="true" lazy="false" cascade="all" ></many-to-one>        
</class>

甚至没有开始:

Caused by: org.hibernate.MappingException: Duplicate property mapping of systemObject found in ar.com.portal.bean.Customer

但我知道这可行,因为如果删除“多对一”,则INSERT语句中存在WORKSPACE_ID列的值(但没有OBJECT_ID则失败)

所以...我有这个属性,我需要它同时是一个多对一的关系和组件,但Hibernate不喜欢这样。还有另一种方法可以解决这种特殊情况吗?或者我要使用命名查询编写自定义插入?

1 个答案:

答案 0 :(得分:0)

bean应该是

public class Customer {
    private Integer id;
    private String code;
    private SystemObject systemObject = new SystemObject();    
    private Workspace workspace= new Workspace ();    
}

然后映射应该是

<class name="ar.com.portal.bean.Customer" table="CUSTOMER">
    <id name="id" column="CUSTOMER_ID" >
        <generator class="increment"></generator>
    </id>
    <property name="code" column="CODE" />
    <component name="workspace" class="ar.com.framework.base.Workspace" >
        <property name="workspaceId" column="WORKSPACE_ID" />
    </component>
    <many-to-one name="systemObject" class="ar.com.framework.base.SystemObject" column="OBJECT_ID" 
            unique="true" not-null="true" lazy="false" cascade="all" ></many-to-one>        
</class>