2011-01-17 1 views
3

Например, у меня есть два класса: Person and Employee (Employee - подкласс Person). Лицо: имеет фамилию и имя. Сотрудник: имеет также зарплату.Как преобразовать ORM в свой подкласс с помощью Hibernate?

На стороне клиента у меня есть одна форма HTML, где я могу заполнять информацию о человеке (например, фамилию и имя). У меня также есть «переключатель» между «Лицом» и «Сотрудником», и если переключатель включен в Employee, я могу заполнить поле зарплаты.

С серверной стороны сервлеты получают информацию от клиента и используют инфраструктуру Hibernate для создания/обновления данных в/из базы данных. Отображение, которое я использую, представляет собой единую таблицу для лиц и сотрудников с дискриминатором.

Я не знаю, как преобразовать Person к Employee, путем модификации его type, который используется в качестве DiscriminatorColumn.

я поначалу пытался:

  • нагрузки Людей р из базы данных
  • создать пустую Соискатель Адрес объект
  • значения копирования из р в е
  • установить значение заработной платы
  • сохранить e в базе данных

Но я не мог, поскольку Я также копирую идентификатор, и поэтому Hibernate рассказал мне, где два экземпляра ORM с одним и тем же идентификатором.

И я не могу отдать Личность в Работника напрямую, так как Лицо - это Суперкласс Работника.

Там, кажется, грязный способ: удалить человек и создать сотрудник с теми же информациями, но я не очень нравится ..

Так что я был бы признателен за любую помощь по этому поводу :)

Некоторые уточнения:

человек класс:

public class Person { 

    protected int id; 

    protected String firstName; 
    protected String lastName; 

    // usual getters and setters 
} 

класс сотрудника:

public class Employee extends Person { 

    // string for now 
    protected String salary; 

    // usual getters and setters 
} 

И в сервлет:

// type is the "switch" 
if(request.getParameter("type").equals("Employee")) { 
    Employee employee = daoPerson.getEmployee(Integer.valueOf(request.getParameter("ID"))); 
    modifyPerson(employee, request); 
    employee.setSalary(request.getParameter("salary")); 
    daoPerson.save(employee); 
} 
else { 
    Person person = daoPerson.getPerson(Integer.valueOf(request.getParameter("ID"))); 
    modifyPerson(employee, request); 
    daoPerson.save(person); 
} 

И, наконец, нагрузка (в дао):

public Contact getPerson(int ID){ 
    Session session = HibernateSessionFactory.getSession(); 
    Person p = (Person) session.load(Person.class, new Integer(ID)); 
    return p; 
} 

public Contact getEmployee(int ID){ 
    Session session = HibernateSessionFactory.getSession(); 
    Employee = (Employee) session.load(Employee.class, new Integer(ID)); 
    return p; 
} 

С этим, я получаю ClassCastException при попытке загрузить Person используя getEmployee.

XML Hibernate отображения:

<class name="domain.Person" table="PERSON" discriminator-value="P"> 
     <id name="id" type="int"> 
      <column name="ID" /> 
      <generator class="native" /> 
     </id> 

     <discriminator column="type" type="character"/> 


     <property name="firstName" type="java.lang.String"> 
      <column name="FIRSTNAME" /> 
     </property> 
     <property name="lastName" type="java.lang.String"> 
      <column name="LASTNAME" /> 
     </property> 

    <subclass name="domain.Employee" discriminator-value="E"> 
    <property name="salary" column="SALARY" type="java.lang.String" /> 
    </subclass> 
</class> 

достаточно ли ясно?: -/

+0

Извините, я полностью не понял ваш вопрос, пока не прочитал ваш последний свой пост. Поэтому я удалил свой пост, он больше не держится. –

+0

@ Adeel: По моей вине, я сначала не был достаточно ясен (без каких-либо реализаций). И спасибо за ваши ответы в любом случае :) – Vincent

ответ

4

Когда я сделал обзор несколько лет назад, я нашел плохой взлом, который мог бы решить вашу проблему.

Когда я понимаю вас правильно - вам нужно превратить Человека в Работника и обратно. Они использовали столбец дискриминатора, назовем его «диск» и предположим, что вы используете дискриминатор String с двумя значениями PERSON и EMPLOYEE. Затем вам понадобится дополнительный столбец, который отображает столбец дискриминатора для класса Person. Назовем это «hackType».

@Column(columnName=”disc”) 
private String hackType; 

Теперь у вас есть связанный hackType и тип объекта. Сначала вам нужно убедиться, что hackType - ЧЕЛОВЕК для всех людей и EMPLOYEE для всех сотрудников. - Но если вы хотите «перенести» Person на сотрудника, вам просто нужно загрузить Person (по идентификатору), установить его поле hackType в EMPLOYEE, сохранить его, очистить кеш и перезагрузить его (по идентификатору) как Наемный рабочий.

Но это действительно плохой взлом, я видел его для nHibernate, но я предполагаю, что он может работать и для спящего режима Java. - В любом случае Я настоятельно рекомендую не делать этого таким образом,, но интересно знать этот хак.

По крайней мере, я полагаю, проблема в том, что ваша модель домена неверна: Сотрудник не должен быть подклассом Person. Потому что это будет означать, что Сотрудник всегда будет Работником, а Человек (если он создан как Человек) никогда не станет Работником. Я настоятельно рекомендую строить отношения 1: 1 между Лицом и Работником. Где Person является основным объектом, а Employee - необязательным расширением для Person. (В этом случае вам нужно переименовать Employee в какую-то вещь, например EmploymentFacts, чтобы четко указать, что это только часть Employee человека.)

+0

Нет, Ральф, у нас есть правильный путь. Я понятия не имею о много лет назад, никогда не дотрагивался до Hibernate, или сказал на начальных этапах. ;) –

+0

Я понял ваше решение, но это явно грязное: D И да, модель домена может быть неправильной, но у меня нет выбора, и я не могу ее изменить: - Но спасибо за ваше решение, я попробую это, поскольку это единственное решение, которое я получил до сих пор. – Vincent

+0

@ Adeel Ansari: что это за правильный путь? Я верю Employee emp = em.find (Employee.class, "personId"); не работает. – Ralph

0

Я не думаю, что есть хороший выход. Вы можете запустить запрос обновления для человека, чтобы изменить его тип на «E» и изменить зарплату, после чего вы можете получить его с помощью getEmployee(), если вам это еще нужно.

Смежные вопросы