直接在 JPA/JPQL 中将行插入连接表?

Eri*_* B. 5 java jpa jpql jpa-2.0 spring-data-jpa

JPA 中有没有办法将行直接插入连接表?我有以下合同和附件实体:

public class Contract implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Version
    @Column(name = "version")
    private Integer version;

    private String number;
    private String volume;

    @ManyToMany
    @JoinTable(joinColumns = @JoinColumn(name = "contract_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "attachment_id", referencedColumnName = "id"))
    private List<Attachment> attachments;
}
Run Code Online (Sandbox Code Playgroud)

Attachment 实体:

public class Attachment implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Version
    @Column(name = "version")
    private Integer version;

    private String name;
}
Run Code Online (Sandbox Code Playgroud)

由于线程并发问题,我想直接将附件添加到合同中,而无需加载合同,将附件添加到列表中并持久/保存合同,因为合同对象本身没有更新数据。更详细一点,我有多个线程并行保存附件,如果我要在所有这些线程中持久化合约,我需要进行某种并发控制以避免 OptimisticLockExceptions。鉴于没有修改 Contract 实体(只有连接表),我不想陷入瓶颈,只直接更新连接表。

在 JPA 和/或 JPQL 中有没有办法将行直接插入连接表?工作流程是保留附件,然后将适当的行插入连接表。

有没有办法从实体中检索 JPA 生成的连接表名称?

DDL:

CREATE TABLE `contract` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `number` varchar(255) DEFAULT NULL,
  `volume` varchar(255) DEFAULT NULL,
  `version` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;


CREATE TABLE `attachment` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `version` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=197 DEFAULT CHARSET=utf8;


CREATE TABLE `contract_attachment` (
  `contract_id` bigint(20) NOT NULL,
  `attachment_id` bigint(20) NOT NULL,
  UNIQUE KEY `UK_27094bpt88d7bfngq5v52jrs` (`attachment_id`),
  KEY `FK_i1ycj6ewd536bky08t0jjh15d` (`contract_id`),
  CONSTRAINT `FK_i1ycj6ewd536bky08t0jjh15d` FOREIGN KEY (`contract_id`) REFERENCES `contract` (`id`),
  CONSTRAINT `FK_27094bpt88d7bfngq5v52jrs` FOREIGN KEY (`attachment_id`) REFERENCES `attachment` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Run Code Online (Sandbox Code Playgroud)

小智 0

看起来您需要将级联属性添加到 @ManyToMany 注释。使用“持久”或“全部”。
但这确实是不清楚的描述,你说你不想加载Contract,但是你如何在不加载的情况下持久/保存Contract?

如果您确实不想加载合约而只是保留附件,则需要将 @ManyToMany 关系添加到您的附件中。然后添加合同(您仍然需要加载它,但不需要将其更新为最新)。应该是这样的:

@ManyToMany
@JoinTable(joinColumns = @JoinColumn(name = "attachment_id", referencedColumnName = "id"), inverseJoinColumns =  @JoinColumn(name = "contract_id", referencedColumnName = "id"))
private List<Contract> contracts;
Run Code Online (Sandbox Code Playgroud)