字段“record\u id”没有默认值-spring jpa错误

wsewodh2  于 2021-07-23  发布在  Java
关注(0)|答案(5)|浏览(418)

我正在为已经开发的springbootweb应用程序添加一个特性。具有子实体的主实体是记录。它有一些列/变量,我现在希望这些列/变量位于它自己的独立实体(customerorder)中,并且与记录以一对一的关系存在。总结一下:
记录{
-事情1
-事情2
-事情3
}
现在变成:
客户订单{
-事情1
-事情2
-事情3
}
记录{customerorder}
我对我的作品有一些问题。以下是customerorder模型的相关关系数据:

@Entity
@Table(name="customer_orders")
public class CustomerOrder {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    ... other columns

    @OneToOne(orphanRemoval = true, cascade = CascadeType.ALL, mappedBy="customerOrder", fetch = FetchType.EAGER)
    private Record record;

}

下面是记录模型的相关数据:

@Entity
@Table(name="records")
public class Record extends Auditable<String> implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    ... other columns

    @OneToOne
    @JoinColumn(name="customer_order_id", nullable = false, unique = true)
    private CustomerOrder customerOrder;
}

当我尝试发布记录时,当用户尝试在ui中创建记录时,我的问题就存在了。以下是记录的post方法:

@PostMapping
    public ResponseEntity<?> saveRecord(@RequestBody Record recordBody, BindingResult result) {
        if(!result.hasErrors()) {
            if(recordBody.getHardwareItems().isEmpty()) {
                record = recordsService.save(recordBody);
            } else {
                // Save the record first, recordId is required on hardwareItems
                // TODO: investigate Spring Hibernate/JPA rules - is there a way to save parent before children to avoid a null recordId
                CustomerOrder customerOrder = recordBody.getCustomerOrder();
                recordBody.setCustomerOrder(new CustomerOrder());
                customerOrder.setRecord(record);
                customerOrder = customerOrdersService.save(customerOrder);
                record = recordsService.save(recordBody);
            }
        } else {
            return new ResponseEntity<>(result.getAllErrors(), HttpStatus.BAD_REQUEST);
        }
        // Return the location of the created resource
        uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{recordId}").buildAndExpand(record.getId()).toUri();
        return new ResponseEntity<>(uri, HttpStatus.CREATED);
    }

我收到的错误如下:

2021-02-19 02:35:50.989  WARN 31765 --- [nio-8080-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1364, SQLState: HY000
2021-02-19 02:35:50.989 ERROR 31765 --- [nio-8080-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper   : Field 'record_id' doesn't have a default value

这至少对我来说是有意义的,因为我正在尝试保存依赖于记录对象的customerorder对象,该对象尚未被持久化。那么,如何更改顺序和/或创建并持久化记录对象,以便将customerorder对象保存到其中呢?
另外,我正在使用mysql,这是我已经拥有的迁移脚本。我必须在这里为客户订单表添加一些内容吗?

-- Add a sample user
INSERT IGNORE INTO users (first_name, last_name, email, password, enabled, role)
VALUES ('Sample', 'User', 'sample@email.com', 'sample password', true, 'ROLE_ADMIN');

-- Customer Reference Values
INSERT IGNORE INTO customers (name) VALUES ('value1');
INSERT IGNORE INTO customers (name) VALUES ('value2');
INSERT IGNORE INTO customers (name) VALUES ('value3');
INSERT IGNORE INTO customers (name) VALUES ('value4');
INSERT IGNORE INTO customers (name) VALUES ('value5');
INSERT IGNORE INTO customers (name) VALUES ('value6');
INSERT IGNORE INTO customers (name) VALUES ('value7');
INSERT IGNORE INTO customers (name) VALUES ('value8');

下面是records表和customerorders表的mysql脚本:

-- -----------------------------------------------------
-- Table `myapp`.`records`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `myapp`.`records` (
  `id` BIGINT NOT NULL AUTO_INCREMENT,
  `customer_order_id` BIGINT NOT NULL,
  `record_id` BIGINT NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `UK_7m7wsqy68b7omkufvckoqv2hf` (`customer_order_id` ASC) VISIBLE,
  INDEX `FKta31a9q1llknlo2n0jw741987` (`customer_id` ASC) VISIBLE,
  CONSTRAINT `FK3q3clytyrx7s8edp9ok821j3`
    FOREIGN KEY (`customer_order_id`)
    REFERENCES `myapp`.`customer_orders` (`id`),
  CONSTRAINT `FKta31a9q1llknlo2n0jw741987`
    FOREIGN KEY (`customer_id`)
    REFERENCES `myapp`.`customers` (`id`))
ENGINE = InnoDB
AUTO_INCREMENT = 27
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;

-- -----------------------------------------------------
-- Table `myapp`.`customer_orders`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `myapp`.`customer_orders` (
  `id` BIGINT NOT NULL AUTO_INCREMENT,
  `record_id` BIGINT NOT NULL,
  `record_id_test` BIGINT NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `UK_ilew9pg8y4qnyhmjg38k1fev2` (`record_id_test` ASC) VISIBLE,
  INDEX `FK5rpb3u59bblj7h70wjr5mvb01` (`record_id` ASC) VISIBLE,
  CONSTRAINT `FK5rpb3u59bblj7h70wjr5mvb01`
    FOREIGN KEY (`record_id`)
    REFERENCES `myapp`.`records` (`id`),
  CONSTRAINT `FKk7a0g7djyhymr54ehoftkhyfw`
    FOREIGN KEY (`record_id_test`)
    REFERENCES `myapp`.`records` (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;
3pmvbmvn

3pmvbmvn1#

架构与实体不匹配。您的customer\u orders表不应具有record\u id列。指定记录表应具有列customer\u order\u id。使用注解显式定义该列:

@JoinColumn(name="customer_order_id", nullable = false, unique = true)

然而,你的注解在另一边

@OneToOne(orphanRemoval = true, cascade = CascadeType.ALL, mappedBy="customerOrder", fetch = FetchType.EAGER)

指示这只是使用另一个表中的外键的backref。从架构中删除列。我假设db模式中的其他列(而不是实体)与用例无关,因为您有注解说您的实体有其他字段。但是,外键没有意义,并且它与您的实体不匹配。从数据库架构中删除列。

lrpiutwd

lrpiutwd2#

如果我的理解是正确的,你在一对一的关系中有一个双向Map。所以, customer_order 有一个 record_id 列和 record 有一个 customer_order_id 列。这并不理想,而且hibernate不支持这种类型的自动Map。如果您仔细想想,如果两列都不可为空,那么您就不能保存数据b/c您不能同时保存这两列。你得先救一个。
如果你想保持这个,你必须使其中一个不可为空。然后保存一个,然后保存另一个,然后用您现在生成的另一个的id重新保存第一个。
hibernate正在尝试保存 customer_order 首先,你们所说的信用证 customer_order_id 是在 records 表,并且不可为null。这是默认值。我建议保留这个,去掉另一个 record_id 中的列 customer_orders table。
更新:为了澄清,这里有一个解决方案。由于record\u id和record\u id\u test不可为空,请在代码中设置它们的值,然后保存。应该有用。
如果我错过了什么,请提供更多的信息,如基础数据库,数据库的位置 record_id 模型中的列等。

gdrx4gfi

gdrx4gfi3#

拆下两个 record_id 列或为其提供默认值。它们没有Map到实体中的任何内容,因此hibernate没有将它们包含在insert语句中,这会导致失败,因为它们都配置为 NOT NULL .
我猜他们是想在 Record 以及 CustomerOrder ,但它被Map到 customer_order_id 通过

@JoinColumn(name="customer_order_id", nullable = false, unique = true)
vngu2lb8

vngu2lb84#

在表创建脚本中,似乎还包括一个名为 RECORD_IDRECORDS table。它已经有了标准 ID 列来存储主键。不确定你是否真的需要 RECORD_ID 列在那里。在表创建脚本中被标记为NOTNULL并且没有设置默认值,因此会出现错误。
查看表创建脚本中的约束,看起来应该命名为 CUSTOMER_ID 而不是 RECORD_ID .
第一步请检查这个。

os8fio9y

os8fio9y5#

添加 @OneToOne(cascade = CascadeType.PERSIST) 对于customerorder变量上面的注解,我基本上只需要做一些事情就可以解决这个问题。这个小组的另一个开发者帮了我。然后,我可以在post方法中去掉对customerorder值的所有引用,只需要在put方法中为customerorder设置一个setter。

相关问题