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

  1. Получить родителя tr с помощью .closest()
  2. Получить значение code с помощью .attr()
  3. [1117 ] Получить совпадающие строки, получив родительскую таблицу, а затем элементы tr, имеющие одинаковые code, используя атрибут , равный селектору .
  4. Получить индекс с помощью .index()
  5. Пример:

    $("input[type='text']").change(function() {
    
      var $parent = $(this).closest("tr");
      var code = $parent.attr("code");
      var $codeRows = $(this).closest("table").find("tr[code='" + code + "']");
      var index = $codeRows.index($parent);
    
      console.log(index);
    });
    
    

    ]

12
задан Deleted User 1 July 2014 в 17:55
поделиться

4 ответа

Jorge I found one solution on http://forums.sun.com/thread.jspa?threadID=518416 which works.

Create the below class in your project. Whereever you creating object of ObjectInputStream, use DecompressibleInputStream instead and it deserializes the old object with the new version Id class.

public class DecompressibleInputStream extends ObjectInputStream {

    public DecompressibleInputStream(InputStream in) throws IOException {
        super(in);
    }


    protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
        ObjectStreamClass resultClassDescriptor = super.readClassDescriptor(); // initially streams descriptor
        Class localClass = Class.forName(resultClassDescriptor.getName()); // the class in the local JVM that this descriptor represents.
        if (localClass == null) {
            System.out.println("No local class for " + resultClassDescriptor.getName());
            return resultClassDescriptor;
        }
        ObjectStreamClass localClassDescriptor = ObjectStreamClass.lookup(localClass);
        if (localClassDescriptor != null) { // only if class implements serializable
            final long localSUID = localClassDescriptor.getSerialVersionUID();
            final long streamSUID = resultClassDescriptor.getSerialVersionUID();
            if (streamSUID != localSUID) { // check for serialVersionUID mismatch.
                final StringBuffer s = new StringBuffer("Overriding serialized class version mismatch: ");
                s.append("local serialVersionUID = ").append(localSUID);
                s.append(" stream serialVersionUID = ").append(streamSUID);
                Exception e = new InvalidClassException(s.toString());
                System.out.println("Potentially Fatal Deserialization Operation. " + e);
                resultClassDescriptor = localClassDescriptor; // Use local class descriptor for deserialization
            }
        }
        return resultClassDescriptor;
    }
}
18
ответ дан 2 December 2019 в 07:04
поделиться

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

Если возможно, вы можете изменить таблицу с помощью столбца, чтобы указать, был ли обработан сериализованный объект. Затем выполните проходы по таблице для каждого serialVersionUID , где вы попытаетесь обработать любые объекты, с которыми еще не работали. Вы можете перехватить исключение InvalidClassException и перейти к следующей записи, если ваш модуль обновления обнаружит сериализованный объект, который он не обрабатывает, записав номер версии, чтобы вы могли сделать еще один проход.

Это немного утомительно, но очень просто.

Сериализация Java имеет несколько очень полезных функций для поддержки эволюции классов. Тем не менее, вы должны знать, что вы делаете. Может случиться так, что все объекты на самом деле имеют одинаковые данные, но не было уделено внимания поддержанию идентификатора версии.

Вы можете продолжать использовать сериализацию, когда все объекты обновлены до одной и той же версии. Просто будьте осторожны, когда вы добавляете в класс новые поля, которые имеют смысл с их значениями по умолчанию (булевы значения равны false, объекты равны нулю, целые числа равны нулю и т. Д.).

1
ответ дан 2 December 2019 в 07:04
поделиться

Вы сможете обойти проблему, переопределив ObjectInputStream.readClassDescriptor .

Использование XMLEncoder на самом деле не поможет с миграцией версий, так как правила совместимости во многом совпадают. На самом деле, вероятно, следует сохранять объект в реляционной форме с помощью инструмента ORM.

Вероятно, разные serialVersionUID произошли из-за различных синтетических членов, генерируемых javac. Отправьте предупреждения и вставьте serialVersionUID в.

1
ответ дан 2 December 2019 в 07:04
поделиться

Я могу что-то упустить, но это звучит так, как будто вы пытаетесь сделать что-то более сложное, чем необходимо. Что произойдет, если:

(a) вы берете текущее определение класса (т.е. исходный код) и жестко кодируете его серийный UID к старому (или одному из старых), а затем используете это определение класса для десериализации сериализованные экземпляры?

(б) в байтовом потоке, который вы читаете, вы заменяете старые серийные UID новыми, прежде чем оборачивать их ObjectInputStream?

ОК, просто чтобы уточнить (б). Так, например, если у меня есть маленький класс, подобный этому:

  public static class MyClass implements Serializable {
    static final long serialVersionUID = 0x1122334455667788L;
    private int myField = 0xff;
  }

, то когда данные сериализуются, это выглядит примерно так:

ACED000573720011746573742E546573 ’..sr..test.Tes
74244D79436C61737311223344556677 t$MyClass."3DUfw
880200014900076D794669656C647870 ?...I..myFieldxp
000000FF ...ÿ

Каждая строка составляет 16 байтов, а каждый байт - 2 шестнадцатеричных цифры. Если вы посмотрите внимательно, во второй строке, 9 байтов (18 цифр), вы увидите, что начинается серийный идентификатор версии (1122 ...). Таким образом, в наших данных здесь (ваши будут немного отличаться), смещение идентификатора серийной версии составляет 16 + 9 = 25 (или 0x19 в шестнадцатеричном формате). Поэтому, прежде чем я начну десериализацию, если я захочу изменить идентификатор этой последовательной версии на что-то другое, мне нужно записать свой новый номер со смещением 25:

byte[] bytes = ... serialised data ...
ByteBuffer bb = ByteBuffer.wrap(bytes);
bb.putLong(25, newSerialVersionUID);

, тогда я просто продолжу как обычно:

ObjectInputStream oin = new ObjectInputStream(new ByteArrayInputStream(bytes));
MyClass obj = (MyClass) oin.readObject();
1
ответ дан 2 December 2019 в 07:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: