2013-06-07 2 views
5

Hibernate бросает следующее исключение:(Hibernate) java.sql.SQLException: Поле «хххх» не имеет значения по умолчанию

Caused by: java.sql.SQLException: Field 'catVerb_id' doesn't have a default value 

Люди говорят, что проблема с моим, которые имеют первичные ключи не оператор AUTO_INCREMENT, однако вы можете видеть, что я сделал это в своей базе данных, и проблема продолжается. Итак, я привел свои классы и мои реализации в базе данных.

Я думаю, что моя проблема связана с классом тестирования ... Кто-нибудь может показать мне, как я могу это проверить?

(Да, некоторые слова на португальском языке, но вы можете понять).

CategoriaVerbete

@Entity 
@Table(name="verbete_categoria") 
public class CategoriaVerbete implements Serializable{ 
    private long id; 
    private String nome; 
    private String descricao; 
    private int serie; 
    private Set<Verbete> verbetes = new HashSet<Verbete>(); 
    private Set<SignificadosVerbete> significados = new HashSet<SignificadosVerbete>(); 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name="catVerb_id") 
    public long getId() { 
     return id; 
    } 
    public void setId(long id) { 
     this.id = id; 
    } 

    ... 

    @OneToMany(cascade = {CascadeType.ALL}) 
    @JoinColumn(name="catVerb_id", nullable = true) 
    public Set<Verbete> getVerbetes() { 
     return verbetes; 
    } 
    public void setVerbetes(Set<Verbete> verbetes) { 
     this.verbetes = verbetes; 
    } 

    @OneToMany(cascade = {CascadeType.ALL}) 
    @JoinColumn(name="catVerb_id", nullable = true) 
    public Set<SignificadosVerbete> getSignificados() { 
     return significados; 
    } 
    public void setSignificados(Set<SignificadosVerbete> significados) { 
     this.significados = significados; 
    } 

} 

Verbete

@Entity 
@Table(name="verbete") 
public class Verbete implements Serializable{ 
    ... 

    @ManyToOne 
    @JoinColumn(name="catVerb_id", insertable = false, updatable = false) 
    public CategoriaVerbete getCategoria() { 
     return categoria; 
    } 
    public void setCategoria(CategoriaVerbete categoria) { 
     this.categoria = categoria; 
    } 

    ... 
} 

SignificadosVerbete

@Entity 
@Table(name="verbete_significados") 
public class SignificadosVerbete { 
    ... 

    @ManyToOne(cascade = CascadeType.ALL) 
    @JoinColumn(name="catVerb_id", insertable = false, updatable = false) 
    public CategoriaVerbete getCategoria() { 
     return categoria; 
    } 
    public void setCategoria(CategoriaVerbete categoria) { 
     this.categoria = categoria; 
    } 

    ... 

} 

В базе данных ...

CREATE TABLE verbete_categoria (
catVerb_id INT PRIMARY KEY NOT NULL AUTO_INCREMENT, 
catVerb_nome VARCHAR(100) UNIQUE, 
catVerb_descricao MEDIUMTEXT, 
catVerb_serie INT NOT NULL 
); 

Любая помощь будет оценена, спасибо.

ОБНОВЛЕНИЕ - ПРОБЛЕМА решаемые

Ну, я ожидал триумфальный саундтрек, но это нормально ...

Я просто следовал тому, что эта ссылка говорит:

https://www.ibm.com/developerworks/community/blogs/fd26864d-cb41-49cf-b719-d89c6b072893/entry/como_criar_relacionamento_onetomany_com_hibernate?lang=en

Я читал, что то, что в этой ссылке не рекомендуется в документации Hibernate, но я старался следовать рекомендациям и просил одну неделю обрабатывать ошибки. Поэтому я надеюсь, что это поможет другим людям.

И спасибо за все ответы.

+0

Объявление аннотаций над идентификатором поля, а не методом get. – fmodos

+0

Но я читал, что мы можем определить аннотации по методам get или по полям, и это нехорошо использовать оба в одном классе ... Я читал неправильно? – vitorgreati

+0

не уверен, каждая ссылка, которую я использую ... объявляется над полем, где вы его читали? – fmodos

ответ

0

Если вы используете один и тот же столбец catVerb_id для @JoinColumn как

@JoinColumn(name="catVerb_id", nullable = true) 

попытки изменить его

@JoinColumn(name="catVerb_id", insertable = false, updatable = false) 

И это не может быть пустым, потому что это первичный ключ в вашем случае.

+0

Я пробовал, но проблема продолжается =/ – vitorgreati

+0

Попробуйте также: @GeneratedValue (стратегия = GenerationType.IDENTITY) – Alex

+0

Для OneToMany используйте OneToMany (targetEntity =, mappedBy =) вместо JoinColumn – Alex

2

Я согласен с предоставленной ссылкой. Он работал по ссылке. Как я понял, удаление нижней части действительно сработало для меня.

До:

@ManyToOne(cascade = CascadeType.ALL) 
@JoinColumn(name="catVerb_id", insertable = false, updatable = false) 

После:

@ManyToOne(cascade = CascadeType.ALL) 
@JoinColumn(name="catVerb_id") 
+0

Это сработало и для меня, мне любопытно узнать твердый ответ, почему это работает. Я обновлю ответ с тем, что получаю в ближайшем будущем –

3

Я считаю, что это SignificadosVerbete вставка вызывает проблему «не может быть пустым» (настоятельно рекомендуем вам включить трассировки SQL, чтобы увидеть, какой запрос вызывает проблему).

Это распространенная проблема для двунаправленных отношений «один ко многим». У вас есть что-то вроде:

class Foo { 
    @Id 
    @Column("foo_id") 
    Long id; 

    @OneToMany(cascade=ALL) 
    @JoinColumn("foo_id") 
    Set<Bar> bars; 
} 

class Bar { 
    @Id 
    @Column("bar_id") 
    Long id; 

    @ManyToOne 
    @JoinColumn("foo_id", insertable=false, updatable=false) 
    Foo foo; 
} 

Такое сопоставление приведет к тому, что отношения будут принадлежать Foo. И это создаст несколько операторов insert + update. Когда вы вставляете Foo, с 2 Bar s, что произойдет, он сначала вставляет это Foo и 2 Bar без FK foo_id. Затем будет выпущено два обновления для каждого Bar для обновления правильного foo_id в таблице Bar.

Обычно мы не отображение двунаправленного OneToMany отображения как это, мы делаем это вместо:

class Foo { 
    @Id 
    @Column("foo_id") 
    Long id; 

    @OneToMany(mappedBy="foo", cascade=ALL) 
    Set<Bar> bars; 
} 

class Bar { 
    @Id 
    @Column("bar_id") 
    Long id; 

    @ManyToOne 
    @JoinColumn("foo_id") 
    Foo foo; 
} 

Поступая таким образом, отношения owened по Bar, и когда вы вставляете как то, что я описал выше , вы будете вставлять 1 Foo и 2 Bar s, которые уже имеют foo_id как часть вставки.

Как правило, мы делаем двунаправленные отношения в спящем режиме.

+0

oops, только что прочитали ваше обновление этого документа, что, кажется, предлагает то, что я описываю здесь. Невозможно прочитать португальский язык: P –

+0

Это ответ, который решил проблему. Большое спасибо, Адриан! Я не знал, что эти квалификаторы (обновляемые, вставные) могут повлиять на операции. Думаю, мне нужно глубоко рассказать о том, как hiberante переводит это на операции sql. – gruszczy

+0

Рад помочь (ничего себе, почти 2 года.). Подумайте о принятии ответа, если он решит вашу проблему. –

1

java.sql.SQLException: Поле 'хххх' не имеет значения по умолчанию

(ака косвенный Fetch.LAZY вопрос нагрузки.)

Я столкнулся с этой проблемой Cегодня.

В моей ситуации оказалось несколько проблем.

Первое, что я обнаружил, что нужно было исправить, заключалось в том, что список, о котором идет речь, должен быть ЛАЗИРОВАННЫЙ. И LAZY LOADED Я имею в виду, что к нему нужно получить доступ из базы данных, когда база данных «находится в сеансе». Теперь есть небольшой трюк, который я нашел, что вам нужно делать, когда вы имеете дело с Fetch.LAZY, , так что вам нужно (казалось бы, бесполезно) вызывать метод на указанном объекте при его загрузке в контейнер. Недостаточно просто вернуть ссылку, даже внутри объекта сеанса.

Например, вместо того, чтобы просто сказать это:

public List<Apple> getApples(Kid kid) throws KidNotFoundException 
{ 
    log.info("getApples (service) called"); 
    kid = get(kid); 
    List<Apple> list = kid.getApples(); 
    return list; 
} 

Вы должны добавить еще один, казалось бы, незначительный шаг. Чтобы вызвать механизм Lazy Load JPA, вам нужно вызвать метод на самом ссылочном объекте (и он работает только в том случае, если внутри транзакции JPA, прямой или подразумеваемой с помощью тега @Stateless). До тех пор, пока JPA будет делать это, лучше не загружать ненужные объекты в память (ака. вся идея Fetch.LAZY).

Так что в данном случае я называю метод на извлеченном (Fetch.LAZY обозначение) объекта «список»:

list.size(); 

Любой метод на объект может быть вызван, чтобы вызвать JPA, чтобы загрузить объект (или объекты), в этом случае я просто вызвал метод list.size(), был настолько удобным, что он не выглядит неуместным, а просто вызывает на первый взгляд ненужный kid.getName(); с профессиональной точки зрения. Как я хочу, хороший учебник по Fetch.LAZY мог бы все это указать мне. Корм для другой книги, я думаю ...

Это заставляет JPA фактически загружать указанный объект из базы данных.

public List<Apple> getApples(Kid kid) throws KidNotFoundException 
{ 
    log.info("getApples (service) called"); 
    kid = get(kid); 
    List<Apple> list = kid.getApples(); 
    list.size(); 
    return list; 
} 

Это был первый вопрос, порождающий «java.sql.SQLException: Поле„хххх“не имеют значения по умолчанию» сообщение в моем случае.

Вторая проблема связана с неправильно настроенным отношением @ManyToMany между двумя таблицами. Сегодня потребовалось около пяти минут, чтобы настроить то, что я считал отношением «многие ко многим» от ранее созданного прототипа, который у меня был. Потребовалось около шести часов вытягивания волос, чтобы получить изломы. В любом случае, это то, что я сделал для решения моей ситуации.

/** 
* "Buckets" 
* an Apple can be give to 0-to-n Kids ... 
*/ 

@ManyToMany(cascade=CascadeType.PERSIST) 
@JoinTable(name="Buckets", 
    [email protected](name="Apple_id"), 
    [email protected](name="Kid_id")) 
private List<Kid> kids; 

public List<Kid> getKids() { 
    return kids; 
} 

public void setKids(List<Kid> kids) { 
    this.kids = kids; 
} 

. , ,

/** 
* a Kid can have 0-n Apples 
*/ 

@ManyToMany(mappedBy="kids", cascade=CascadeType.PERSIST) 
private List<Apple> apples; 

Это и тот факт, что моя первоначальная настройка @ManyToMany была ссылающейся неправильный столом способствовал этой ошибке в моем случае. Но простая фиксация ситуации LAZY LOAD разрешила «java.sql.SQLException: Поле» xxxx «не имеет проблемы по умолчанию» сразу.

Perry

Ps. После целого дня я изучил некоторые аккуратные трюки, скрытые под грубым внешним видом JPA (например, серфинг в Интернете и чтение документов о том, как эффективно использовать отношения @ManyToMany). Таким образом, приведенная выше конфигурация будет динамически создавать третью таблицу базы данных, которая выглядит так же хорошо, как если бы вы ее создали вручную. Он также обеспечивает уникальную взаимосвязь между детьми и яблоками, что касается отношений «один-к-одному». А также создайте только одну дополнительную таблицу в базе данных, вместо необходимости иметь две идентичные таблицы в базе данных. В действительности, в моем случае я имел 2 таблицы до этого @ManyToMany конструкции:

Дети Яблоки

В результате @ ManyTo @ Многие конструкции, перечисленные выше, так же, как сейчас у меня 3:

Детские Яблоки Ковши

Внутри таблицы Ведра есть только два поля, Apple_id и Kid_id и что важно то, что, когда я добавить запись как:

kids.add(apple); 
apple.add(kids); 

Существует только одна запись в таблице Ведра, а не две! Это очень важно, если вы пытаетесь использовать Список <> вместо набора <>, (он же уникальный).

Смежные вопросы