Hibernate抛出以下异常:
Caused by: java.sql.SQLException: Field 'catVerb_id' doesn't have a default value
人们说问题在于我的PK没有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
);
任何帮助将不胜感激,谢谢。
更新 - 已解决的问题
好吧,我期待一个胜利的配乐,但没关系......
我只是按照这个链接说的那样:
我读到Hibernate文档不推荐该链接中的内容,但我尝试按照建议进行操作并通过一周处理错误。所以,我希望这有助于其他人。
感谢所有答案。
答案 0 :(得分:5)
我认为导致SignificadosVerbete
问题的是cannot be null
插件(我强烈建议您打开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} {{1} } s,将会发生的事情是它会先插入Bar
,然后插入2 Bar 而不使用 FK Foo
。然后,将为每个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;
}
拥有,当您按照我的描述插入时,您将插入1 Bar
和2 Foo
已经拥有Bar
作为插入的一部分。
我们通常如何在Hibernate中进行双向关系。
答案 1 :(得分:2)
我同意所提供的链接。它遵循链接。据我了解, 删除下面的部分对我有用。
之前:
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="catVerb_id", insertable = false, updatable = false)
后:
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="catVerb_id")
答案 2 :(得分:1)
java.sql.SQLException:Field&#39; xxxx&#39;没有默认值
(又名。间接Fetch.LAZY加载问题)
我今天遇到了这个问题。
在我的情况下,原来是一些问题。
我发现必须修复的第一件事是有问题的名单需要被拉上加载。并且通过LAZY LOADED我的意思是当数据库&#34;在会话中时必须从数据库访问&#34;。现在有一个小技巧,我发现你在处理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;
}
你必须再添加一个看似微不足道的步骤。要触发JPA的Lazy Load机制,您需要在引用的对象本身上调用一个方法(它只能在JPA事务内部工作,无论是直接还是隐含的@Stateless标记)。直到你这样做,JPA将做到最好不要将不必要的对象加载到内存中(也就是说。 Fetch.LAZY背后的整个想法)。
所以在这种情况下,我在检索到的(Fetch.LAZY指定)对象&#39;列表&#39;上调用一个方法。 :
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;
}
这是生成&#39; java.sql.SQLException的第一个问题:Field&#39; xxxx&#39;没有默认值&#39;在我的情况下的消息。
第二个问题与两个表之间未正确配置的@ManyToMany关系有关。今天,我花了大约五分钟来设置我之前创建的原型的多对多关系。需要大约六个小时的时间才能解决问题。无论如何,这就是我最终要解决的问题。
/**
* "Buckets"
* an Apple can be give to 0-to-n Kids ...
*/
@ManyToMany(cascade=CascadeType.PERSIST)
@JoinTable(name="Buckets",
joinColumns=@JoinColumn(name="Apple_id"),
inverseJoinColumns=@JoinColumn(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:Field&#39; xxxx&#39;没有默认值&#39;问题立刻。
佩里
聚苯乙烯。 一整天之后,我确实学到了一些隐藏在JPA粗糙外表下的巧妙技巧(也就是说,浏览网页和阅读有关如何有效使用@ManyToMany关系的文档)。这样,上面的配置将动态创建第三个数据库表,看起来就像手动创建它一样好。就一对一的关系而言,它还强制了孩子和苹果之间的独特关系。除了在数据库中只创建一个额外的表,而不是在数据库中需要两个相同的表。实际上,在我的情况下,我在这个@ManyToMany构造之前有2个表:
儿童 苹果
由于上面列出的@ ManyTo @ Many结构,我现在有3:
儿童 苹果 水桶
在Buckets表中只有两个字段,Apple_id和Kid_id,重要的是当我向两个字段添加一个条目时:
kids.add(apple);
apple.add(kids);
Buckets表中只有一条记录而不是两条记录!如果您尝试使用List&lt;&gt;这一点非常重要代替Set&lt;&gt;,(又名。唯一)。
答案 3 :(得分:0)
如果您使用相同的列catVerb_id
作为@JoinColumn
@JoinColumn(name="catVerb_id", nullable = true)
尝试将其更改为
@JoinColumn(name="catVerb_id", insertable = false, updatable = false)
并且它不能为空,因为它是您案例中的主键。