Я разрабатываю приложение на javafx, которое подключается через RMI к EAR. Этот EAR подключается к базе данных SQLServer и отображает POJOS в спящем режиме.
Эти POJOS содержат двунаправленные отношения OneToMany и ManyToOne. Как следствие, эти отношения отображаются как Список.
Company.java
@Entity
@Table(name = "Company")
public class Company implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column(name = "id_company",nullable = false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@OneToMany(mappedBy = "company",cascade = CascadeType.ALL )
@ElementCollection
private List<Client> Clients;
//GETTERS&SETTERS
}
Client.java
@Entity
@Table(name = "Client")
public class Client implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column(name = "id_client",nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ManyToOne
private Company company;
//GETTERS&SETTERS
}
Когда я выполняю это, T - это Компания:
public default T selectById(Serializable id, Class<T> entityClass,Session session)throws HibernateException {
T obj = null;
obj = session.get(entityClass, id);
return obj;
}
Результатом является POJO со всей соответствующей информацией, но в режиме отладки посмотрите следующее:

Объект успешно создан, и мое настольное приложение получает объект отлично, но если объект снова отправил его на сервер с помощью метода, который получает в качестве параметра объект Company, то у меня возникает эта ошибка.
javax.ejb.EJBException: java.io.StreamCorruptedException: serialVersionUID does not match!
at org.jboss.as.ejb3.remote.AssociationImpl.receiveInvocationRequest(AssociationImpl.java:128)
at org.jboss.ejb.protocol.remote.EJBServerChannel$ReceiverImpl.handleInvocationRequest(EJBServerChannel.java:450)
at org.jboss.ejb.protocol.remote.EJBServerChannel$ReceiverImpl.handleMessage(EJBServerChannel.java:188)
at org.jboss.remoting3.remote.RemoteConnectionChannel.lambda$handleMessageData$3(RemoteConnectionChannel.java:430)
at org.jboss.remoting3.EndpointImpl$TrackingExecutor.lambda$execute$0(EndpointImpl.java:926)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.io.StreamCorruptedException: serialVersionUID does not match!
at org.jboss.marshalling.AbstractClassResolver.resolveClass(AbstractClassResolver.java:108)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadClassDescriptor(RiverUnmarshaller.java:1025)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadNewObject(RiverUnmarshaller.java:1354)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:275)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:223)
at org.jboss.marshalling.river.RiverUnmarshaller.readFields(RiverUnmarshaller.java:1856)
at org.jboss.marshalling.river.RiverUnmarshaller.doInitSerializable(RiverUnmarshaller.java:1769)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadNewObject(RiverUnmarshaller.java:1397)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:275)
at org.jboss.marshalling.river.RiverUnmarshaller.doReadObject(RiverUnmarshaller.java:208)
at org.jboss.marshalling.AbstractObjectInput.readObject(AbstractObjectInput.java:41)
at org.jboss.ejb.protocol.remote.EJBServerChannel$RemotingInvocationRequest.getRequestContent(EJBServerChannel.java:805)
at org.jboss.as.ejb3.remote.AssociationImpl.receiveInvocationRequest(AssociationImpl.java:126)
... 7 more
Caused by: an exception which occurred:
in field com.persistence.pojo.Company.Clients
in object com.persistence.pojo.Company@47368172
in object of type com.persistence.pojo.Company
Я использую сервер Wildfly10.x. Версия hibernatecore - 5.2.17.Final
Прошу прощения, если это очень плохо объяснено, но дело в том, что проект довольно сложный, по сути, мне понадобится спящий режим для сопоставления с объектом List, а не с Persistentbag.




Проблема здесь в том, что объект, который вы получаете из спящего режима, относится к некоторому прокси-классу спящего режима, а не к вашему фактическому классу сущности. Это нормальное поведение для спящего режима. Этот прокси-класс создается автоматически, как и serialVersionUID.
В общем, сериализация / отправка объектов класса сущностей напрямую не является хорошей практикой из-за таких проблем, но также из-за проблем с отложенной инициализацией и всех тех, которые связаны с привязкой объектов к контексту диспетчера сущностей.
Наиболее распространенное решение - создать «объекты передачи данных» или DTO, которые могут иметь одинаковые поля (или очень похожие - например, заменить перечисления на строки и т. д., В зависимости от того, что вам нужно), и ничего больше. на основе вашего примера у вас может быть такой класс:
public class CompanyDTO implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private List<ClientDTO> Clients;
//GETTERS&SETTERS
}
(по аналогии вам тоже нужно создать класс ClientDTO).
Вместо этого используйте этот класс для внешнего (где внешний вид не обязательно удален, просто там, где вам нужно отключиться от контекста EM) связи.
Вы можете заполнить его вручную или любым другим способом (например, с помощью отражения с помощью BeanUtils, конструктора с аргументом Company, который копирует свойства [этого я бы не советовал, поскольку он прерывает разделение уровня приложения, но для целей этого разговора это действительный способ сделать это]). Единственное, что важно, это то, что вы заполняете его из контекста диспетчера сущностей.
Нет, насколько мне известно, это невозможно сделать
@Zeromus Если я сделаю то, что вы сказали во втором комментарии, коллекция по-прежнему является PersistentBag. И первый комментарий я не очень понял.
В вашем Client Entity вам нужно сгенерировать динамический serialVersionUID, сгенерировать такой
private static final long serialVersionUID = -558553967080513790L;
Вы можете увидеть в этой ссылке, как сгенерировать serialVersionUID. Для получения дополнительной информации см. Этот отклик.
У меня также была конфигурация serialVersionUID, как вы говорите, и выдает ту же ошибку.
Всегда использовать один и тот же идентификатор, например 1L, означает, что в будущем, если определение класса будет изменено, что приведет к изменениям в структуре сериализованного объекта, возникнет большая вероятность возникновения проблем при попытке десериализации объекта. Итак, попробуйте использовать сгенерировать идентификатор серийной версии. Не используйте 1 л.
Идея состоит в том, чтобы сгенерировать идентификатор, который является уникальным для определенной версии класса, который затем изменяется, когда в класс добавляются новые детали, такие как новое поле, которое повлияет на структуру сериализованного объекта.
Я знаю причины, по которым существует serialversionUID и почему он должен быть уникальным для каждого класса. Спасибо, что сказали мне, но, как я уже сказал, как будто это с уникальным серийным номером, как будто это 1L ошибка, которую я объяснил ранее, продолжает появляться. Спасибо.
Добавьте конструктор по умолчанию в свои классы и попробуйте очистить файлы проекта .class и перестроить проект.
использование другого serialVersionUID ничего не изменит. Проблема здесь в том, что объект, который OP пытается сериализовать, на самом деле принадлежит к другому классу, чем кажется (прокси-класс спящего режима)
Поначалу моя идея заключалась в том, чтобы не использовать DTO и вместо этого использовать ленивую инициализацию. Например, если мне нужен список компаний от клиента, я бы вызвал метод, который возвращает список компаний, и то, как они имеют ленивую инициализацию, менее сложны. С другой стороны, если я хочу войти в одну из этих компаний, чтобы показать их данные на экране, я бы сделал еще один запрос на получение компании по их идентификатору, которая инициализировала бы список клиентов перед его отправкой. По вашему комментарию я понимаю, что нет способа заставить спящий режим создать список без прокси. не? Спасибо.