(Hibernate)java.sql.SQLException:字段'xxxx'没有默认值

时间:2013-06-07 00:43:55

标签: java hibernate

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
);

任何帮助将不胜感激,谢谢。

更新 - 已解决的问题

好吧,我期待一个胜利的配乐,但没关系......

我只是按照这个链接说的那样:

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

我读到Hibernate文档不推荐该链接中的内容,但我尝试按照建议进行操作并通过一周处理错误。所以,我希望这有助于其他人。

感谢所有答案。

4 个答案:

答案 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) 

并且它不能为空,因为它是您案例中的主键。