Как «нарезать» POJO - PullRequest
1 голос
/ 22 июля 2010

Я заимствую значение "ломтик" из C ++.

Допустим, у меня есть простой POJO, который сохраняется через Hibernate:

class Person {
private long id;
private String name;
...
// getters and setters here
...
}

Теперь, когда я извлекаю объект из базы данных, я знаю, что он "инструментирован" Hibernate (его реальный класс - это объект, сгенерированный автоматически). Я хочу преобразовать его обратно в «простой» объект человека. Tnat будет использоваться, например, для отправки объекта в XStream и получения результата, содержащего только то, что содержит Person.

Я мог бы сделать это, определив конструктор копирования, но я не хочу иметь проблемы с записью конструкторов копирования для каждого класса ORM (не говоря уже о нарушении принципа DRY).

Так что мне было интересно, если

а) уже есть Java-библиотека, которая это делает? б) Если нет, то было бы целесообразно написать один, используя отражение?

В случае (b) любые рекомендации / рекомендации / скелеты кода будут приветствоваться.

Ответы [ 4 ]

3 голосов
/ 22 июля 2010

Библиотека отображения bean-компонентов Dozer отлично справляется с этой задачей и очень проста в использовании.

Просто сопоставьте экземпляр компонента, возвращаемого Hibernate, своему классу:*

Person person = session.load(...);
BeanMapper mapper = ...;
Person cleanPerson = mapper.map(person, Person.class);

вуаля, больше никаких прокси-серверов Hibernate или загруженных ленивых коллекций!

1 голос
/ 22 июля 2010

Здесь интересная дискуссия о вашей проблеме

http://www.mojavelinux.com/blog/archives/2006/06/hibernate_get_out_of_my_pojo/

В комментариях предлагается несколько решений.В частности

http://code.google.com/p/entity-pruner/

http://www.anzaan.com/2010/06/serializing-cglib-enhanced-proxy-into-json-using-xstream/

Лично я очень разбираюсь в разделении слоев и могу утверждать, что классы, которые вы хотите сериализовать по проводам или в XMLна самом деле должны быть отделены от ваших классов слоя доступа к данным, что также решило бы проблему.

class SerializablePerson
{
   ... fields you care about ...
   SerializablePerson(Person person)
   {
      ... set only what you care about ... 
   }

}
1 голос
/ 22 июля 2010

Класс org.apache.commons.beanutils.BeanUtilsBean, вероятно, делает почти все, что вы хотите.Метод copyProperties будет вызывать геттеры в вашей сущности и искать сеттеры с соответствующим именем свойства для целевого объекта, который вы предоставляете.Вам может потребоваться обработать некоторые вложенные сущности, в зависимости от того, какое поведение вы хотите, и если / как вы отображаете отношения.

Если вам требуется более сложный способ, вы можете зарегистрировать конвертер для преобразования вложенных типов сущностей вчто-то еще.

0 голосов
/ 22 июля 2010

У вас может быть класс Person без персистентной информации, заключенный в постоянный аналог, например:

public class Person implements Serializable
{
   private String name;
   // others.
}

public class PersistentPerson
{
   private Long id;
   private Person data; //

   public Person getPerson() { return this.data; } 
}

Я не уверен, что дизайн того стоит. Двойная модель заставляет меня немного рвать, когда я пишу этот пример.

Большой вопрос: почему вы считаете это необходимым? Если нет хорошего способа сказать XStream, что он не должен включать id при сериализации, я бы сказал, что было бы лучше написать свои собственные javax.xml.bind.Marshaller и javax.xml.bind.Unmarshaller, чтобы получить то, что вы хотите.

Существуют более эффективные способы решения этой проблемы, чем разрушение всего вашего дизайна.

...