отображение «один ко многим» // как отобразить ассоциацию устаревших таблиц (Hibernate) - PullRequest
1 голос
/ 11 мая 2009

У меня есть две устаревшие таблицы базы данных, расположенные в упрощенном виде, например:

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 ссылка на строку n строка в таблице SLAVE. Учитывая описание столбца сверху, возможная совокупность может быть

MASTER                        SLAVE
100                           42
'labl'                        'labl'
1                             1
'some label'                  0.1
                              43
                             'labl'
                              1
                              0.2

Теперь, используя hibernate, как я могу отразить эти отношения в моих классах Java? В ScenarioMaster я бы объявил набор или список с общедоступными получателями / установщиками, такими как

private List<ScenarioSlave> slaves = new ArrayList<ScenarioSlave>();

Отображения гибернации для ScenarioMaster могут содержать

<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>

Это, однако, создает оператор обновления strage при обновлении уже персистентного объекта ScenarioMaster с использованием session.saveOrUpdate(scenarioMaster).

// 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.

РЕДАКТИРОВАТЬ : составной ключ откладывается в отдельный класс с помощью этого сопоставления

<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' , которую затем можно использовать как id для зимней спячки. Я полагаю, это то, что делает Hibernate (без использования реальной таблицы).

Ответы [ 2 ]

2 голосов
/ 11 мая 2009

Hibernate не работает с композитными ключами, по моему опыту. Насколько я видел, это одна из главных проблем с Hibernate. Я работал над этим в прошлом, избегая использования «чисто» составных ключей; то есть я дал таблицам составных ключей уникальный столбец идентификаторов, с которым Hibernate может затем работать

0 голосов
/ 12 мая 2009

Я немного постарался (должен любить Apache Derby ), делая вид, что обе таблицы не имеют составного идентификатора. Затем я узнал, что оператор 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 ...

...