Hibernate JPA @JoinColumn(nullable = false)如何仅生成数据库约束,特别是在一种@ManyToOne方法中

时间:2019-01-29 17:04:38

标签: java hibernate jpa

这不是重复的问题,其他问题没有相同的情况

我的问题类似于此注释:nullable = false not only create database constraint,但是他的解决方案禁用了休眠中的所有检查可为空性,这是我不想要的,我特别希望在这种@ManyToOne关系中使用它。

我有一个RegraValidacao.java类,只能将其@ManyToOne字段之一设置为其他字段,其他字段为null。那些@ManyToOne关系是通过@JoinTable建立的。我想要的是:当通过 spring.jpa.properties.hibernate.hbm2ddl.auto 生成DDL时,我希望@JoinTable批注中的@JoinColumns可以在db2数据库上生成数据库约束NOT NULL。

因此,RegraValidacao可以与实体ContaLimite.java和Documento.java建立@ManyToOne可为空的关系。可以保留仅具有ContaLimite.java的RegraValidacao,例如:

RegraValidacao rgr = new RegraValidacao();
rgr.setContaLimite(new ContaLimite());
rgr.setDocumento(null);

hibernate.save(rgr) // SHOULD WORK

但是当我在JoinColumn上设置 nullable = false 时,它不会让Documento字段为空。

@Entity
public class RegraValidacao {

    @ManyToOne
    @JoinTable(name = "CDR_CONTA_LIMITE_REGRA", 
    joinColumns = {@JoinColumn(name = "RGR_ID", nullable = false)},
    inverseJoinColumns = {@JoinColumn(name = "CDL_ID", nullable = false)})
    private ContaLimite contaLimite;

    @ManyToOne
    @JoinTable(name = "DOR_DOCUMENTO_REGRA",
    joinColumns = {@JoinColumn(name = "RGR_ID", nullable = false)}, 
    inverseJoinColumns = {@JoinColumn(name = "DOM_ID", nullable = false)})
    private Documento documento;
}

编辑:为简单起见,我只添加了这两个属性,但实际上我在此类中有8对Attributtes / JoinTables。又为什么呢?因为这种关系是相互排斥的。如果我有一个普通的表关系@ManyToOne而没有JoinTables,则我在数据库上将有7个空字段,并有1个集合。使用JoinTables时,我将没有任何null字段,并且如果在JoinTable中设置了ID,则肯定在相关的表上有一个条目。

换句话说,与ContaLimite.java和Documento.java的关系应为:optional = true,但它们在@JoinTable上的列应为nullable = false。

我期望的是 通过hbm2ddl.auto生成的表:

CDR_CONTA_LIMITE_REGRA --> RGR_ID NOT NULL, CDL_ID NOT NULL //OK
DOR_DOCUMENTO_REGRA --> RGR_ID NOT NULL, CDL_ID NOT NULL //OK

通过Hibernate持续存在:

RegraValidacao rgr = new RegraValidacao();
rgr.setContaLimite(new ContaLimite());
rgr.setDocumento(null);

hibernate.save(rgr) // SHOULD BE OK!

我得到的: 通过hbm2ddl.auto生成的表:

CDR_CONTA_LIMITE_REGRA --> RGR_ID NOT NULL, CDL_ID NOT NULL //OK
DOR_DOCUMENTO_REGRA --> RGR_ID NOT NULL, CDL_ID NOT NULL //OK

通过Hibernate持续存在:

RegraValidacao rgr = new RegraValidacao();
rgr.setContaLimite(new ContaLimite());
rgr.setDocumento(null);

hibernate.save(rgr) --> Error, cannot persist null

ERROR: org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value : br.system.regravalidacao.RegraValidacao.documento; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value : br.system.regravalidacao.RegraValidacao.documento

这样,我希望JoinTable的列具有NOT NULL约束,但是我仍然可以使用Documento为空的持久化RegraValidacao。

2 个答案:

答案 0 :(得分:0)

您将联接表用于两个属性。我不推荐这个。

如果我正确理解了您的问题,则您希望Documento为空,或者同时设置Documento或ContaLimite。所以我只允许Documento为空。

答案 1 :(得分:0)

好吧,我找到了合适的解决方案,但这并不是我想要的。希望有一天能对某人有所帮助。

我想从Hibernate Runtime禁用对类的特定属性的检查null,这是我无法实现的。我可以为整个班级RegraValidacao.java禁用它

我创建了一个Spring @Configuration类包,其范围为一个.properties文件(在我的/ resources目录中),其上带有 spring.jpa.properties.hibernate.check_nullability = false ,然后使用@ComponentScan我的课程包:

RegraValidacaoConfiguration.java:

@Configuration
@PropertySource("classpath:regravalidacao.properties")
@EntityScan(RegraValidacaoConfiguration.PACKAGE)
@ComponentScan({RegraValidacaoConfiguration.PACKAGE})
class RegraValidacaoConfiguration {
    static final String PACKAGE = "br.system.regravalidacao";
}

RegraValidacao.java:

package br.system.regravalidacao;
public class RegraValidacao {
    //...
}

regravalidacao.properties:

spring.jpa.properties.hibernate.check_nullability=false

这样,我的整个项目仍将具有 spring.jpa.properties.hibernate.check_nullability = true (默认),并且只有我的软件包 br.system.regravalidacao 将是错误的。

唯一的伤害是我在RegraValidacao内部的其他属性(其中一些是@OneToOne)将受到check_nullability = false的错误影响,这就是为什么我想要某些属性范围而不是类范围的原因。尽管这种伤害还算不错,因为我仍然会收到这些属性的错误,不是从Hibernate Runtime,而是从数据库。对我来说还可以。