JPA OneToMany和ManyToOne:错误-列不允许为NULL

3

我正在使用Hibernate作为JPA提供者。有两个实体:

@Entity
@Table(name = "PROYECTOS")
public class Proyecto {
    @Id
    private Long id;
    ...
    @OneToMany(mappedBy = "proyecto", cascade = CascadeType.PERSIST, orphanRemoval = true)
    private List<Incidencia> incidencias;
    ...
}

@Entity
@Table(name = "INCIDENCIAS")
public class Incidencia {
    @Id
    private Long id;
    ...
    @ManyToOne(cascade = CascadeType.PERSIST, optional = false)
    @JoinColumn(name = "ID_PROYECTO", nullable = false)
    @NotNull
    private Proyecto proyecto;
    ...
    public Incidencia(Proyecto proyecto, Usuario usuario, String descripcion,
        Date fechaYHora) {
        super();
        this.proyecto = proyecto;
        this.usuario = usuario;
        this.descripcion = descripcion;
        this.fechaYHora = fechaYHora;
    }
    ...
}

当我执行一个测试方法并试图持久化"Incidencia"类("Proyecto"在之前已经被持久化)时:

...
entityManager.persist(proyecto);
entityManager.flush();
...
Incidencia incidencia = new Incidencia(proyectoFind, usuario,
                "1ª incidencia del proyecto", new Date());
proyecto.getIncidencias().add(incidencia);
entityManager.persist(proyecto);
entityManager.flush();
...

最后一次刷新时抛出了异常:
    ... 35 more
Caused by: org.h2.jdbc.JdbcBatchUpdateException: La columna "PROYECTO" no permite valores nulos (NULL)
NULL not allowed for column "PROYECTO"; SQL statement:
insert into INCIDENCIAS (DESCRIPCION, FECHA_Y_HORA, ID_PROYECTO, ID_USUARIO, ID) values (?, ?, ?, ?, ?) [23502-175]
    at org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1167)
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
    ... 41 more

我确信"proyecto"被设定在"Incidencia"中,在其构造函数中:
this.proyecto = proyecto;

所以,我不明白为什么会抛出这个异常。

非常感谢任何帮助。


1
你是否检查了 proyectoFind 是否有非空值? - ProgrammerDan
你必须使用适当的英文单词来命名你的变量和类。读你的代码真是一场苦难!!! - Svetlin Zarev
对不起,我在这个问题中没有使用英语单词来表示变量和类。这是我的第一个问题,我没有注意到这个问题。下次我会尝试用英语单词来表示所有东西。 我检查了“proyecto”(我错误地称之为“proyectoFind”),它没有空值。 非常感谢。 - user3470079
异常信息:Caused by: org.h2.jdbc.JdbcBatchUpdateException: 列“PROYECTO”不允许为空值(NULL) 列“PROYECTO”不允许为空值;SQL 语句: insert into INCIDENCIAS (USUARIO_CREACION, FECHA_CREACION, DESCRIPCION, FECHA_Y_HORA, USUARIO_ULTIMA_MODIFICACION, FECHA_ULTIMA_MODIFICACION, ID_PROYECTO, ID_USUARIO, VERSION, ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [23502-175]。这个句子中出现的列与我在类中定义的相同。列“PROYECTO”没有在类中定义。供您参考,我正在使用内存数据库 H2。 - user3470079
如果您删除flush的调用会发生什么? - JamesB
显示剩余2条评论
2个回答

1

最终,我已经成功解决了这个问题。 在我展示的两个类中,映射没有任何问题。我之前展示的有关Proyecto和Incidencia的映射是不同的。Incidencia类使用了一个带有Id类的复合主键:

@Entity
@Table(name = "INCIDENCIAS")
@IdClass(IncidenciaKey.class)
public class Incidencia implements Serializable { 
    @Id
    @Column(name = "ID")
    private Integer id;
    @Id
    @Column(name = "ID_PROYECTO", nullable = false, insertable = false, updatable = false)
    private Long idProyecto;

    @ManyToOne(cascade = CascadeType.PERSIST)
    @NotNull
    @Valid
    private Proyecto proyecto;
...
}

我只是将这个旧版本的Incidencia重新命名了,因此有两个类都使用了@Table(name ="INCIDENCIAS")。我想这就是问题所在。在内存数据库中仍然有一个名为“PROYECTO”的列,它来自于这个已被重命名的实体,而我错误地认为它没有被使用。
当我将重命名的Incidencia类移出与数据库一起构建的包后,一切都正常工作了。
对于提出这个不准确问题,我想道歉。
感谢您的帮助。

0

在这行代码之后

proyecto.getIncidencias().add(incidencia);

你需要在 incidencia 对象上设置一个后向引用

incidencia.setProyecto(proyecto);

然后刷新。

你在构造函数中将proyectoFind传递给incidencia,然后将同一个对象添加到不同的Proyecto对象中似乎不正确。


谢谢你的回答。 很抱歉,“proyectoFind”是我写的代码中的错误。 我还尝试使用默认构造函数并设置“Incidencia”的变量,而不是使用带参数的构造函数。 我还检查了“proyecto”没有空值。 我也像你建议的那样在“incidencia”对象上设置了一个反向引用。 但是仍然会抛出相同的异常。 - user3470079
所以,我使用: Incidencia incidencia = new Incidencia(proyecto, usuario, "项目的第一个问题", new Date()); 而不是: Incidencia incidencia = new Incidencia(proyectoFind, usuario, "项目的第一个问题", new Date()); 但是仍然抛出相同的异常。 - user3470079
项目的主键设置了吗? - JamesB
是的,没错。在持久化proyecto对象并flush之后,我检查了proyecto的所有属性,它们都是正确的,包括它的主键(id)。然后,我使用这个proyecto创建了incidencia对象,将incidencia添加到proyecto中,在incidencia对象上设置了一个反向引用(我认为这是多余的),最后再次flush。但是仍然抛出了异常。 - user3470079

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接