我有两个遗留数据库表,以简化的方式布局:
MASTER SLAVE
ident ident
sName sName
sNumber sNumber
sDesc sValue
----- ------
Java Class 'ScenarioMaster' Java Class 'ScenarioSlave'
每一行都有ident
列的代理索引,但MASTER.key
和SLAVE.key
之间没有任何关系。但是,对于MASTER
表,一个sName / sNumber对的唯一性为true。因此,这将是一个可能且有意义的复合键(我知道那些是邪恶的)。
实际上,有一个1:n关系意味着MASTER
表中每个SLAVE
行引用 n 行。鉴于上面的列描述,可能的人口可能是
MASTER SLAVE
100 42
'labl' 'labl'
1 1
'some label' 0.1
43
'labl'
1
0.2
现在,使用hibernate,我怎么能在我的java类中反映这种关系?在ScenarioMaster
中,我将使用公共getter / setter声明一个Set或List,如
private List<ScenarioSlave> slaves = new ArrayList<ScenarioSlave>();
ScenarioMaster
的hibernate-mappings可以包含
<bag name="slaves" cascade="all">
<key>
<column name="sName" not-null="true"/>
<column name="sNumber" not-null="true"/>
</key>
<one-to-many class="ScenarioSlave"/>
</bag>
但是,在使用ScenarioMaster
更新已经持久的session.saveOrUpdate(scenarioMaster)
实体时,这会创建一个strage更新语句。
// create master scn and slave slv
scn.addSlave(slv);
session.saveOrUpdate(scn);
Hibernate:
update
SLAVE
set
sNumber=?,
sName=?,
sValue=?
where
sName=?
and sNumber=?
Hibernate:
update
SLAVE
set
sName=null,
sNumber=null
where
sName=?
and sNumber=?
我做错了什么?第二次更新来自哪里?
我想这与sName / sNumber不是ScenarioSlave
的关键有关。我无法弄明白,为什么。
请注意,sName / sNumber参数确实指向有效值,并且我想通过ScenarioMaster
保留的saveOrUpdate
实例实际上在{{ScenarioSlave
实例中有一个非空slaves
实例1}}列表。
编辑:使用此映射将复合键推迟到单独的类
<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_KEY
,它将'labl',1 映射到类似'key_labl1'的表格,然后可以使用作为hibernate的id
。我想,这就是hibernate的作用(不使用实际的表)。
答案 0 :(得分:2)
Hibernate对复合键不起作用。就我所见,这是Hibernate的一个主要问题。我过去曾经通过避免使用“纯粹”的复合键来解决它;也就是说,我给复合键表一个唯一的ID列,然后Hibernate可以使用它。
答案 1 :(得分:0)
我尝试了一下(得到爱Apache Derby)假装,两个表都没有复合ID。
然后我发现,最有可能发出SET ... = null
语句以使slave
列表的成员无效。
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
);
这是我的测试代码。我将主类密钥的生成器设置为assigned
。
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();
然后,在NULL
行中允许SLAVE.number
值,我得到
Hibernate:
update
SLAVE
set
number=null
where
number=?
Hibernate:
update
SLAVE
set
number=?
where
ident=?
现在我只需弄清楚如何在SLAVE
中实际删除陈旧行,而不是将外键列设置为NULL
......