休眠唯一约束

发布于 2024-11-07 00:31:36 字数 1431 浏览 0 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一瞬间的火花 2024-11-14 00:31:36

Hibernate 在该列上创建一个“唯一”索引,然后由数据库强制执行唯一性。

例如,如果你有一个类:

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class UserEmailAddressEntity {
    @Id
    @Basic(optional = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Basic(optional = false)
    private boolean primaryEmail;

    @ManyToOne(optional = false)
    private UserEntity user;

    @NaturalId // this means the email column must be unique
    @Basic(optional = false)
    private String email;

    @Basic(optional = false)
    private String token;

    @Basic(optional = false)
    private boolean verified;
}

Hibernate 创建一个像这样的表:(对于 PostgreSQL,但对于几乎所有 RDBMS 的想法都是相同的)

CREATE TABLE useremailaddressentity
(
  id bigint NOT NULL,
  email character varying(255) NOT NULL,
  primaryemail boolean NOT NULL,
  token character varying(255) NOT NULL,
  verified boolean NOT NULL,
  user_id bigint NOT NULL,
  CONSTRAINT useremailaddressentity_pkey PRIMARY KEY (id),
  CONSTRAINT fk279a5e06c843ec30 FOREIGN KEY (user_id)
      REFERENCES userentity (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,

  -- note the `UNIQUE` here:
  CONSTRAINT useremailaddressentity_email_key UNIQUE (email)
)

Hibernate creates a "unique" index on that column, and it's the database that then enforces the uniquness.

For example, if you have a class:

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class UserEmailAddressEntity {
    @Id
    @Basic(optional = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Basic(optional = false)
    private boolean primaryEmail;

    @ManyToOne(optional = false)
    private UserEntity user;

    @NaturalId // this means the email column must be unique
    @Basic(optional = false)
    private String email;

    @Basic(optional = false)
    private String token;

    @Basic(optional = false)
    private boolean verified;
}

Hibernate creates a table like so: (for PostgreSQL, but the idea is the same for pretty much all RDBMS)

CREATE TABLE useremailaddressentity
(
  id bigint NOT NULL,
  email character varying(255) NOT NULL,
  primaryemail boolean NOT NULL,
  token character varying(255) NOT NULL,
  verified boolean NOT NULL,
  user_id bigint NOT NULL,
  CONSTRAINT useremailaddressentity_pkey PRIMARY KEY (id),
  CONSTRAINT fk279a5e06c843ec30 FOREIGN KEY (user_id)
      REFERENCES userentity (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,

  -- note the `UNIQUE` here:
  CONSTRAINT useremailaddressentity_email_key UNIQUE (email)
)
记忆で 2024-11-14 00:31:36

我尝试复制此行为,我使用 grails 1.3.7 并发现它是可重现的

class Child {
    String name
    static constraints = { name(unique:true) }
}
table created 
CREATE TABLE `child` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(255) NOT NULL,  
  PRIMARY KEY  (`id`),
  UNIQUE KEY `name` (`name`)
)

查询触发
child.save()

Hibernate: select this_.id as id0_0_, this_.version as version0_0_, this_.created_by as created3_0_0_, this_.date_created as date4_0_0_, this_.last_updated as last5_0_0_, this_.name as name0_0_, this_.updated_by as updated7_0_0_ from child this_ where this_.name=?
Hibernate: insert into child (version, created_by, date_created, last_updated, name, updated_by) values (?, ?, ?, ?, ?, ?)

我认为我休眠触发上述查询的原因是检查唯一约束,如果您尝试执行更新,那么此查询将导致内存中具有另一个具有相同标识符的对象,这可能导致非唯一对象异常。

我认为这是休眠而不是 grails,没有在 java/hibernate 中仔细检查这一点。

谢谢

I tried to replicate this behavior , I using using grails 1.3.7 and found it to be reproducible

class Child {
    String name
    static constraints = { name(unique:true) }
}
table created 
CREATE TABLE `child` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(255) NOT NULL,  
  PRIMARY KEY  (`id`),
  UNIQUE KEY `name` (`name`)
)

Queries fired on
child.save()

Hibernate: select this_.id as id0_0_, this_.version as version0_0_, this_.created_by as created3_0_0_, this_.date_created as date4_0_0_, this_.last_updated as last5_0_0_, this_.name as name0_0_, this_.updated_by as updated7_0_0_ from child this_ where this_.name=?
Hibernate: insert into child (version, created_by, date_created, last_updated, name, updated_by) values (?, ?, ?, ?, ?, ?)

The reason i think i hibernate fires the above query is to check the unique constraint, And in case you are trying to perform an update then this query will result in having another object with the same identifier in memory, which could the lead to nonuniqueobjectexception.

I thinking this is hibernate and not grails, have not double checked this in java/hibernate.

Thanks

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文