Проблема в том, что вы храните две базы данных, используя два отдельных файла, используя два отдельных потока сериализации объектов.
Причина, по которой ваш текущий подход не работает для вас, заключается в том, что протокол сериализации объектов хранит ссылки на объекты в виде простых чисел.Он нумерует объекты в потоке как 1, 2, 3 и т. Д. И использует эти номера для ссылки на ранее сериализованные объекты в потоке.
Это работает в контексте одного потока.Но когда у вас есть два или более потоков, у данного объекта могут быть разные номера в каждом потоке.Это означает, что у метода readObject
нет способа узнать, что два объекта в двух разных потоках действительно должны быть связаны друг с другом.
Простое решение состоит в следующем:
ObjectInputStream in = new ObjectInputStream(new FileInputStream("DB.txt"));
for (int i = 0; i < customers.size(); i++) {
out.writeObject(customers.get(i));
}
for (int i = 0; i < shelves.size(); i++) {
out.writeObject(shelves.get(i));
}
Или, что еще лучше, сериализовать списки customers
и shelves
напрямую, потому что это упростит десериализацию.
(Да ... это портит вам текущую структуру кода. Вам придетсязагрузите и сохраните базы данных Customer
и Shelf
в одном месте или передайте открытый поток по всему месту.)
Также возможно хранить объекты в двух отдельных файлах, но вам необходимоиспользовать пользовательские методы сериализации, чтобы сделать это.
Сначала вам нужно решить, в какой файл вы хотите поместить каждый общий дочерний объект;т.е. объекты PhysicalMedia
хранятся в базе данных Customer
или в базе данных Shelf
?
Для каждого класса совместно используемых объектов определите поле идентификатора соответствующего типа;например, String
или `long.Измените свою кодовую базу так, чтобы поле заполнялось значениями, которые являются уникальными в контексте приложения.
Для базы данных, в которой вы хотите разместить объекты, сериализуйте как обычно.
Для других баз данных используйте расширенные функциональные возможности Сериализации объектов, чтобы:
- при записи, заменять объекты (только) их идентификаторами и
- при чтении, найдите идентификаторы в первой базе данных и затем вставьте объект поиска в десериализованный объект.
Для последнего потребуется глубокое знание сериализации объектаAPI, пользовательские сериализации и так далее.В вашем примере у вас есть дополнительная сложность, что объекты, которые вы хотите заменить, являются ключами в Map
объектах.Поскольку вы не можете добавить пользовательские readObject
и writeObject
для стандартного класса карты, вам нужно будет сделать глубокие трюки в пользовательских подклассах самих классов Stream.(И ... нет, я не могу привести вам пример!)
Кроме того: подобные вещи являются одной из причин, по которой нежелательно использовать сериализацию объектов для реализации базы данных.Лучше использовать реальную базу данных и технологию ORM, такую как JPA (например, Hibernate).Есть и другие причины.