te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>java - JPA composite key containing a foreign key with db-generated value - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - JPA composite key containing a foreign key with db-generated value - Stack Overflow

programmeradmin3浏览0评论

Schema

CREATE TABLE Template (
  id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
  -- omitted
);

CREATE TABLE TemplateLabel (
  template_id UUID REFERENCES Template(id) ON DELETE CASCADE,
  code TEXT NOT NULL,
  -- omitted

  PRIMARY KEY (template_id, code)
);

Template has a one-to-many relationship to TemplateLabel. TemplateLabel uses Template.id and a code as a composite primary key.

My current JPA entities (getters, setters, and constructors omitted)

Template.java:

@Entity
public class Template {
    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    private UUID id;

    @OneToMany(mappedBy = "template", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<TemplateLabel> labels;
}

TemplateLabel.java:

@Entity
public class TemplateLabel {
    @EmbeddedId
    private TemplateLabelId id;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("templateId")
    @JoinColumn(name = "template_id")
    private Template template;
}

TemplateLabelId.java:

@Embeddable
public class TemplateLabelId {
    @Column(name = "template_id")
    private UUID templateId;

    private String code;
}

Saving template

I construct the template and pre-fill it with all its labels, setting everything except for Template.id and TemplateLabel.id.templateId, which should have the same value upon inserting into the db.

Template template = Template.builder()
    // all the fields except for id and labels
    .build();
List<TemplateLabel> labels = dto.getLabels().stream().map(label ->
    TemplateLabel.builder()
        .id(new TemplateLabelId(null, label.getCode()))
        .template(template)
        // other fields
        .build()
    ).toList();
template.setLabels(labels);
templateRepository.save(template);

Problem

I would like to generate the ids from the database rather than from the code, and preferably set up the entities in a way so that I can insert a template and some template labels to the database with just one call to repository.save.

In other words, I would like to create a template object with id=null and pre-fill it with some labels (each with id.templateId=null), and just call repository.save on the template, and have the id of the template and all the labels assigned properly, instead of having to call repository.save first with a template to get a db-generated id, and then manully assigning that id to all labels, and then call repository.save again.

With my current configuration, it throws this exception:

Caused by: java.lang.IllegalArgumentException: Can not set java.util.UUID field my.project.entity.TemplateLabelId.templateId to .hibernate.id.IdentifierGeneratorHelper$1

I saw the same exception discussed in another post but the solution there was to use @EmbeddedId, which I'm already using, so I'm wondering what else I should change in my entities.

Additional context

I'm not sure if the template field in my TemplateLabel class is necessary. A unidirectional binding is probably preferred as there will never be a case where I would retrieve a label on its own, but I'm not sure if I can achieve the one repository.save thing I explained above without it. I would also like to remove it and just use the UUID if I can, to keep things simple. But it's a more minor problem (and it seems that it might be less performant too?).

发布评论

评论列表(0)

  1. 暂无评论