大家好!请帮忙。我看了很多有相同错误的线程,但没有找到解决方案。
写入对象时,PostgreSQL序列生成器不起作用。
给出错误信息:
错误:关系“receiving_acts”的“doc_number”列中的空值违反了非空约束
更详细地:
"org.springframework.dao.DataIntegrityViolationException: could not
execute statement; SQL [n/a]; constraint [doc_number\" of relation
\"receiving_acts].
org.hibernate.exception.ConstraintViolationException: could not
execute statement. org.postgresql.util.PSQLException: ERROR: null
value in column \"doc_number\" of relation \"receiving_acts\" violates
not-null constraint\n Подробности: Failing row contains
(feba8451-de26-47c2-9fe2-5381318d8deb, null, 2023-03-01 14:42:03+02,
f, 47a9bb21-fa67-4ff7-bf33-e276d23a19eb)."
有一类Entity:
@Entity
@Table(name = "receiving_acts")
@Getter
@Setter
public class ReceivingAct extends AbstractDocumentEntity {
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ra_dn_gen")
@SequenceGenerator(name = "ra_dn_gen", sequenceName = "receiving_acts_doc_number_seq", allocationSize = 1)
@Column(name = "doc_number")
private Integer docNumber;
@ManyToOne
@JoinColumn(name = "contractor_id", nullable = false)
private Contractor contractor;
@OneToMany(mappedBy = "receivingAct", cascade = CascadeType.ALL)
private List<ReceivingActTSVehiclesLine> tableVehicles;
}
@Id类型字段UUID在类中AbstractDocumentEntity并且没有问题,生成器可以工作。
DDL表创建:
CREATE SEQUENCE IF NOT EXISTS receiving_acts_doc_number_seq AS INTEGER INCREMENT BY 1;
CREATE TABLE receiving_acts
(
id UUID NOT NULL DEFAULT gen_random_uuid(),
doc_number INTEGER NOT NULL DEFAULT nextval('receiving_acts_doc_number_seq'),
date_time TIMESTAMP WITH TIME ZONE NOT NULL,
marked BOOLEAN NOT NULL,
contractor_id UUID NOT NULL,
CONSTRAINT pk_receiving_acts PRIMARY KEY (id),
FOREIGN KEY (contractor_id) REFERENCES contractors (id)
);
控制器类中的方法:
@PostMapping("/")
@ResponseStatus(HttpStatus.CREATED)
public ReceivingActResponse createReceivingAct(@RequestBody ReceivingActRequest docRequest) {
ReceivingAct docEntity = receivingActMapper.toReceivingActEntity(docRequest);
ReceivingAct savedDocEntity = receivingActService.add(docEntity);
return receivingActMapper.toReceivingActResponse(savedDocEntity);
}
add课堂上的方法ReceivingActServiceImpl:
@Override
public ReceivingAct add(ReceivingAct receivingAct) {
return receivingActRepository.save(receivingAct);
}
该方法save是存储库中的标准方法ReceivingActRepository:
public interface ReceivingActRepository extends JpaRepository<ReceivingAct, UUID> {
}
JSON发帖要求:
{
"docDateTime": "2023-03-03 11:53:56",
"contractorId": "47a9bb21-fa67-4ff7-bf33-e276d23a19eb",
"tableVehicles": [
{
"grossWeight": 1564.910,
"vinCodeId": "d7094b75-fefc-4745-a4b6-4c5d4a2f97c3",
"cellId": "bba1f527-a815-41ac-bbf9-aa5433d2d888"
}
]
}
结果,在创建对象时,docNumber它被初始化null,以及id. 但id它返回生成,但docNumber不是。
类型改为Integer,int生成不发生,初始化0,写入0。
数据库中的序列被创建,它被锚定到一个字段。如果您手动添加一行,则会docNumber生成它。
试图@Column添加columnDefinition = "integer default nextval('receiving_acts_doc_number_seq'),没有帮助。
我不知道在哪里看,在哪里挖掘。也许您需要在保存之前以某种方式自己生成它,但这是不合逻辑的。也许当有另一个序列时,需要一种不同的方法。
为了让hibernate在插入时不使用某个字段,可以指定这个字段为ignored(insertable = false)
第二种方案:添加@Generated(GenerationTime.INSERT)注解,向hiber说明该字段会由数据库生成,不需要插入。
我更喜欢第二个选项,因为保存后,生成的字段本质上会立即出现。在第一个选项中,您必须编写获取实体的逻辑。