如何在非 PK 列的 save() 之后获取序列生成的值

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

我的 PostgreSQL 数据库中有一个序列,它在插入时为我的订单表生成 order_number(非主键列):

<createSequence
    sequenceName="order_number_seq"
    startValue="1"
    incrementBy="1"
    cacheSize="1"/>
<addDefaultValue
    tableName="orders"
    columnName="order_number"
    defaultValueComputed="nextval('order_number_seq')"/>

我的问题是保存订单后,order_number 为空: 科特林

// Save order
order = orderRepository.save(order)
// order.orderNumber is null here

sendEmail(order)  // Need order_number here
indexOrder(order) // Need order_number here too

保存后如何检索生成的order_number值?请注意,这不是主键列。

实体:

@Entity
@Table(name = "orders")
class Order(
    @Id val id: UUID = UUID.randomUUID(),
    @Column(name = "order_number", unique = true, nullable = false, updatable = false, insertable = false)
    var orderNumber: Long? = null,
    // other fields...
)

在调用发送电子邮件和索引方法之前,我尝试使用

orderRepository.findById(order.id)
获取实体,但仍然不起作用:订单的 orderNumber 仍然为空

order_number 字段已可插入 false

spring spring-boot kotlin hibernate jpa
1个回答
0
投票

为了在插入上应用默认值,我们需要使用

order_number
:
 从生成的插入 SQL 中删除 
insertable = false

@Entity
@Table(name = "orders")
class Order(
    ...

    @Column(name = "order_number", insertable = false)
    var orderNumber: Long? = null,

    ...
)

因为

order_number
是由数据库填充的,所以您需要在保存后从数据库中获取实体(请参阅下面的测试)。

示例数据库架构 (Postgresql):

CREATE SEQUENCE order_number_seq INCREMENT BY 1 START WITH 1;

CREATE TABLE orders
(
    id           SERIAL PRIMARY KEY,
    order_number INT DEFAULT nextval('order_number_seq') NOT NULL
);

测试

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
import org.testcontainers.containers.PostgreSQLContainer;

import static org.junit.jupiter.api.Assertions.*;

@DataJpaTest
@AutoConfigureTestDatabase
class OrderRepositoryTest {

    @TestConfiguration
    static class PostgresTestContainerConfig {

        @Bean
        @ServiceConnection
        public PostgreSQLContainer<?> postgreSQLContainer() {
            return new PostgreSQLContainer<>("postgres:15-alpine");
        }
    }

    @Autowired
    OrderRepository sut;

    @Autowired
    TestEntityManager entityManager;

    @Test
    void testSave() {
        sut.save(new Order());

        entityManager.clear();
        var orderInDb = entityManager.find(Order.class, 1L);
        assertNotNull(orderInDb.getOrderNumber());
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.