非空且具有默认值的列中的奇怪行为(SpringBoot JPA)

问题描述 投票:0回答:1

在SpringBoot JPA测试过程中发现一个奇怪的行为 请指教。 我想要的是一个具有默认值且不为空的列。 我是这样创建的

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Entity
@DynamicInsert
public class Board {

    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    private Long seq;

    @Column(length = 320, nullable = false)
    @ColumnDefault("'system'")
    /* i don't won't it this way */
//    @Builder.Default
//    private String usrId = "system";
    private String usrId;
}

@SpringBootApplication
public class SpringBootJpaTestApplication {

    private static final Logger log = LoggerFactory.getLogger(SpringBootJpaTestApplication.class);
    
    public static void main(String[] args) {
        SpringApplication.run(SpringBootJpaTestApplication.class, args);
    }

    @Bean
    CommandLineRunner demo(TestRepository repository) {
        return (args) -> {
            
            for(int i = 0; i < 1; i++) {
//                Test test = Test.builder().build();
                Test test = new Test();
                test.setTitle("test title " + i);
                test.setContent("test content " + i);
                
                System.out.println(test.toString());
                
                repository.save(test);
            }
            
            repository.findAll().forEach(test -> {
                log.info(test.toString());
            });
            
            repository.findByTitle("test").forEach(bbs -> {
                log.info(bbs.toString());
            });
            
        };
    }

}

这看起来效果很好。 但是,如果注释掉以下内容,就会出现错误

<!--
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
-->

错误描述

//------------------------------------------------------------ ---------------------------------

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
[2m2024-03-14T23:09:48.901+09:00[0;39m [31mERROR[0;39m [35m2776[0;39m [2m---[0;39m [2m[SpringBootJpaTest] [           main][0;39m [2m[0;39m[36mo.s.boot.SpringApplication              [0;
39m [2m:[0;39m Application run failed

org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value : com.demo.SpringBootJpa.Test.usrId
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:307) ~[spring-orm-6.1.4.jar:6.1.4]
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:241) ~[spring-orm-6.1.4.jar:6.1.4]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550) ~[spring-orm-6.1.4.jar:6.1.4]
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61) ~[spring-tx-6.1.4.jar:6.1.4]
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:335) ~[spring-tx-6.1.4.jar:6.1.4]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152) ~[spring-tx-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:164) ~[spring-data-jpa-3.2
.3.jar:3.2.3]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.4.jar:6.1.4]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:220) ~[spring-aop-6.1.4.jar:6.1.4]
    at jdk.proxy2/jdk.proxy2.$Proxy94.save(Unknown Source) ~[na:na]
    at com.skywhalelab.SpringBootJpa.SpringBootJpaTestApplication.lambda$0(SpringBootJpaTestApplication.java:31) ~[classes/:na]
    at org.springframework.boot.SpringApplication.lambda$callRunner$5(SpringApplication.java:790) ~[spring-boot-3.2.3.jar:3.2.3]
    at org.springframework.util.function.ThrowingConsumer$1.acceptWithException(ThrowingConsumer.java:83) ~[spring-core-6.1.4.jar:6.1.4]
    at org.springframework.util.function.ThrowingConsumer.accept(ThrowingConsumer.java:60) ~[spring-core-6.1.4.jar:6.1.4]
    at org.springframework.util.function.ThrowingConsumer$1.accept(ThrowingConsumer.java:88) ~[spring-core-6.1.4.jar:6.1.4]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) ~[spring-boot-3.2.3.jar:3.2.3]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:789) ~[spring-boot-3.2.3.jar:3.2.3]
    at org.springframework.boot.SpringApplication.lambda$callRunners$3(SpringApplication.java:774) ~[spring-boot-3.2.3.jar:3.2.3]
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[na:na]
    at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[na:na]
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[na:na]
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) ~[na:na]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:774) ~[spring-boot-3.2.3.jar:3.2.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:341) ~[spring-boot-3.2.3.jar:3.2.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) ~[spring-boot-3.2.3.jar:3.2.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-3.2.3.jar:3.2.3]
    at com.skywhalelab.SpringBootJpa.SpringBootJpaTestApplication.main(SpringBootJpaTestApplication.java:16) ~[classes/:na]

//------------------------------------------------------------ ---------------------------------

你能告诉我为什么会发生这种情况吗? 当然,我知道如果我使用 Builder.Default 并给它一个默认值,它就可以正常工作。 但这不是我想要走的方向。我想处理它,以便如果 usrId 变为 null,我不会收到错误并且数据库会输入默认值。

提前谢谢您。

jpa
1个回答
0
投票

嗨:)我认为您对数据库列默认值有误解。

  • 为数据库列指定默认值并不意味着为“空值”设置默认值。 仅供参考,DB 中的 null 表示未知或不适用。
    列默认值是指在插入查询中如果某列为空,则输入相应的值作为默认值。
  • 下面附有差异示例。
  • INSERT INTO BOARD(SEQ) VALUES(1); //this case insert default value in USR_ID INSERT INTO BOARD(SEQ, USR_ID) VALUES(4, null); //NULL not allowed for column
如果尝试在 SQL 查询中输入空值,将会出现 NULL not allowed for columns 错误。
  • 这是因为 nullable = false。
  • 总而言之,JPA 并没有按照提问者的意图发挥作用。

一种方法是使用 SQL 映射器或本机查询发送插入查询。
  • 但是,不建议使用以 SQL 为中心的编程来进行简单查询。
    创建对象时,我更喜欢通过在构造函数中设置其初始值来创建和使用该对象。
  • @Getter @NoArgsConstructor @Entity @DynamicInsert public class Board { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long seq; @Column(length = 320, nullable = false) @ColumnDefault("'system'") private String usrId; public Board(String userId) { if (userId == null || userId.isEmpty()) { this.usrId = "system"; return; } this.usrId = userId; } }
© www.soinside.com 2019 - 2024. All rights reserved.