一对多映射//如何映射遗留表的关联(Hibernate)

一对多映射//如何映射遗留表的关联(Hibernate),hibernate,database-design,orm,Hibernate,Database Design,Orm,我有两个旧式数据库表,以简化的方式排列如下: MASTER SLAVE ident ident sName sName sNumber sNumber sDesc sValue ----- ------ Java Cl

我有两个旧式数据库表,以简化的方式排列如下:

MASTER                        SLAVE
ident                         ident
sName                         sName
sNumber                       sNumber
sDesc                         sValue
-----                         ------
Java Class 'ScenarioMaster'   Java Class 'ScenarioSlave'
每行通过
ident
列有一个代理索引,但是
MASTER.key
SLAVE.key
之间没有关系。但是,对于
MASTER
表,一个sName/sNumber对的唯一性是正确的。因此,这将是一个可能且有意义的复合键(我确实知道那些是邪恶的)

事实上,存在一个1:n关系,这意味着
行引用
表中的n行。根据上面的列描述,可能的人口可能是

MASTER                        SLAVE
100                           42
'labl'                        'labl'
1                             1
'some label'                  0.1
                              43
                             'labl'
                              1
                              0.2
现在,使用hibernate,如何在java类中反映这种关系?在
ScenarioMaster
中,我将声明一个集合或列表,其中包含公共getter/setter,如

private List<ScenarioSlave> slaves = new ArrayList<ScenarioSlave>();
但是,当使用
session.saveOrUpdate(ScenarioMaster)
更新已经存在的
ScenarioMaster
实体时,这会创建一个strage update语句

我做错了什么?第二次更新来自哪里? 我想这与sName/sNumber不是
ScenarioSlave
的键有关。我不太明白,为什么

请注意,sName/sNumber参数确实指向有效值,并且我希望通过
saveOrUpdate
持久化的
ScenarioMaster
实例实际上在
slaves
列表中有一个非空的
ScenarioSlave
实例

编辑:使用此映射将复合键延迟到单独的类

<composite-id name="keyId" class="ScenarioKeyId">
    <key-property name="name" access="field" column="sName"
        type="string" length="20"/>
    <key-property name="number" access="field" column="sNumber"
        type="long"/>
</composite-id>


我真的不想创建一个表
NAMENUMBER\u KEY
,它将'labl',1映射到类似'KEY\u labl1'的东西,然后可以用作hibernate的
id
。我想,这就是hibernate所做的(不使用实际的表)。

根据我的经验,hibernate不能很好地使用复合键。就我所见,这是Hibernate的一个主要问题。过去,我一直通过避免使用“纯”复合键来解决这个问题;也就是说,我给复合键表提供了一个唯一的ID列,Hibernate可以使用它。

我试了一下(不得不爱),假装两个表都没有复合ID。 然后我发现,
设置…=发出null
语句很可能是为了使
从属
列表的成员无效

create table MASTER(
   ident numeric(10) not null, -- key column
   name char(20) not null,
   number numeric(10) not null,
   descr char(64) not null
);

create table SLAVE(
   ident numeric(10) not null, -- key column
   name char(20) not null,
   number numeric(10)   ,      -- foreign key f. MASTER.ident
   value float not null
);
这是我的测试代码。我将主类密钥的生成器设置为分配的

        Master master = new Master();
        master.setIdent(Integer.valueOf(0));
        master.setName("name");
        master.setNumber(42);
        master.setDescr("name/42 descr");
        Slave slv = new Slave("name", 42, 0.001);
        master.addSlave(slv);
        theSession.beginTransaction();
        theSession.saveOrUpdate(master);
        theSession.getTransaction().commit();
然后,允许
SLAVE.number
行中的
NULL
值,我得到

Hibernate: 
    update
        SLAVE 
    set
        number=null 
    where
        number=?
Hibernate: 
    update
        SLAVE 
    set
        number=? 
    where
        ident=?

现在我只需要弄清楚如何实际删除
SLAVE
中的过时行,而不是将外键列设置为
NULL

让我们两人(关于引入唯一Id列)很高兴知道我不是唯一使用该解决方案的人。从DB设计的角度来看,不得不这样做有点令人沮丧,但它确实很好地解决了问题。您能详细介绍一下这种方法吗?当说“给定复合键表一个唯一的ID列”时,您是否更改了表?恐怕我不能这样做,但我也怀疑您是否这样做了。在初始开发期间的测试显示了Hibernate和复合键的问题,因此我们更改了表的初始规范,为该表包含一个单独的主键列。
        Master master = new Master();
        master.setIdent(Integer.valueOf(0));
        master.setName("name");
        master.setNumber(42);
        master.setDescr("name/42 descr");
        Slave slv = new Slave("name", 42, 0.001);
        master.addSlave(slv);
        theSession.beginTransaction();
        theSession.saveOrUpdate(master);
        theSession.getTransaction().commit();
Hibernate: 
    update
        SLAVE 
    set
        number=null 
    where
        number=?
Hibernate: 
    update
        SLAVE 
    set
        number=? 
    where
        ident=?