Как сохранить List & lt; Integer & gt; в таблице с одним столбцом, используя Hibernate? [Дубликат]

В то время как , что вызывает NullReferenceExceptions и подходит к avoid / fix , такое исключение было рассмотрено в других ответах, что многие программисты не имеют " t узнал еще, как независимо отлаживать такие исключения во время разработки.

В Visual Studio это обычно легко благодаря Visual Studio Debugger .


Во-первых, убедитесь, что правильная ошибка будет обнаружена - см. . Как разрешить нарушение «Исключение System.NullReferenceException» в VS2010? Примечание1

Затем либо Начать с отладки (F5) , либо Приложить [отладчик VS] к запуску процесса . Иногда может быть полезно использовать Debugger.Break , в котором будет предложено запустить отладчик.

Теперь, когда NullReferenceException выбрано (или необработанно), отладчик остановится ( помните правило, указанное выше?) в строке, на которой произошло исключение. Иногда ошибка может быть легко обнаружена.

Например, в следующей строке единственный код, который может , вызывает исключение, если myString имеет значение null. Это можно проверить, посмотрев окно Watch или выполнив выражения в окне Immediate Window .

var x = myString.Trim();

В более сложных случаях, таких как следуя ниже, вам нужно будет использовать один из методов выше (Watch или Immediate Windows) для проверки выражений, чтобы определить, было ли str1 пустым или если str2 имеет значение null.

var x = str1.Trim() + str2.Trim();

Once , где было выбрано исключение, это обычно тривиально по отношению к разуму назад, чтобы выяснить, где введенное значение null было [неправильно] -

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


1 Если Break on Throws слишком агрессивен и отладчик останавливается на NPE в библиотеке .NET или сторонних разработчиков, Break на User-Unhandled можно использовать для ограничения выловленных исключений. Кроме того, VS2012 представляет Just My Code , который я рекомендую также включить.

Если вы отлаживаете с включенным Just My Code, поведение немного отличается. При включенном Just My Code отладчик игнорирует исключения, связанные с привилегиями обычного языка (CLR) первого шанса, которые выходят за пределы My Code и не проходят через My Code

8
задан Pascal Thivent 1 May 2010 в 01:33
поделиться

4 ответа

Аннотировать свойство с помощью @Column и определить тип, который будет ArrayList, а не только List. И сделайте Person реализовать Serializable.

Но вы должны сделать это, только если ваши мотивы очень ясны, потому что это правильное решение в некоторых очень редких случаях. Как заметил Паскаль, если вам когда-либо придется менять Person, у вас будут головные боли.

1
ответ дан Bozho 24 August 2018 в 08:40
поделиться
  • 1
    Я уверен, что с ошибкой java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.sql.Blob – Pascal Thivent 23 January 2010 в 11:58
  • 2
    да, я взглянул на один класс, где у меня такая же ситуация - он работает с лобом Lob и с указанием конкретного типа (ArrayList). Обновлен ответ – Bozho 23 January 2010 в 13:15

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

Сначала вам нужно будет использовать атрибут byte[] для хранения сериализованной версии списка лиц, которые будут храниться в BLOB в базе данных. Так что аннотируйте его getter с @Lob (я бы сделал getter и setter private, чтобы не выставлять их). Затем выведите «fake» getter и setter для возврата или установите List<Person> из byte[]. Я использую SerializationUtils из Commons Lang в приведенном ниже примере (предоставит вам собственный вспомогательный класс, если вы не хотите импортировать эту библиотеку) для сериализации / десериализации на лету в / из byte[]. Не забудьте отметить «фальшивый» геттер с помощью @Transcient или Hibernate попытается создать поле (и сбой, потому что он не сможет определить тип для List).

@Entity(name = "family")
class Family implements Serializable {

    // ...

    private byte[] familyMembersAsByteArray;

    public Family() {}

    @Lob
    @Column(name = "members", length = Integer.MAX_VALUE - 1)
    private byte[] getFamilyMembersAsByteArray() { // not exposed
        return familyMembersAsByteArray;
    }

    private void setFamilyMembersAsByteArray((byte[] familyMembersAsByteArray() { // not exposed
        this.familyMembersAsByteArray = familyMembersAsByteArray;
    }

    @Transient
    public List<Person> getFamilyMembers() {
        return (List<Person>) SerializationUtils.deserialize(familyMembersAsByteArray);
    }

    public void setParticipants(List familyMembers) {
        this.familyMembersAsByteArray = SerializationUtils.serialize((Serializable) familyMembers);
    }
}

Не забудьте сделать класс Person Serializable и добавить реальный serialVersionUID (я просто показываю по умолчанию здесь):

public class Person implements Serializable {

   private static final long serialVersionUID = 1L;

   // ...

   private String firstName, lastName;
   private int age;

}

Но пусть пусть я настаиваю, это ужасный дизайн, и он будет очень хрупким (изменение Person может потребовать «переноса» содержимого BLOB, чтобы избежать проблем десериализации, и это станет болезненным. Вы действительно должны пересмотреть эту идею и использовать другую таблицу вместо Person (или я не понимаю, почему вы используете базу данных).

13
ответ дан Pascal Thivent 24 August 2018 в 08:40
поделиться
  • 1
    почему вы не можете использовать пользователя базы данных, может быть, потому что использовать его бессмысленно? Если все, что мне нужно, это хранить список чего-то, мне не нужно помещать его в отдельную базу данных. – Enerccio 20 March 2017 в 11:43
@Type(type = "serializable")
private List<Person> familyMembers;

, если вы не можете использовать аннотации спящего режима, попробуйте это:

@Lob
private Serializable familyMembers;

public List<Person> getFamilyMembers(){
    return (List) familyMembers;
}

public void setFamilyMembers(List<Person> family){
    familyMembers = family;
}
2
ответ дан Sergey Demin 24 August 2018 в 08:40
поделиться

Вы можете создать псевдопрочность (getter и setter), которая принимает / возвращает сериализованную форму и аннотирует familyMembers с помощью @Transient. Это также необходимо будет аннотировать геттеры, а не поля, для всех других свойств.

0
ответ дан Ondra Žižka 24 August 2018 в 08:40
поделиться
Другие вопросы по тегам:

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