将自定义标识符分配给 @id 属性

2023-11-27

我正在将遗留系统迁移到使用 Hibernate 3。它当前生成自己的标识符。为了在尝试将系统转移到更好的系统之前保持系统当前的功能,我将如何指定(使用注释)我自己的类,该类将在发生插入时返回自定义生成的标识符?

就像是:

@Id
@CustomIdGenerator(Foo.class) // obviously this is not a real annotation
public String getId() { ... }

哪里的Foo类有一种生成标识符的方法。

目前我只是打电话给setId(String id)手动方法,但希望有更好的方法来处理这种情况。


我认为没有开箱即用的支持使用纯 JPA-2 API 使用自定义注释生成自定义 Id。但如果您想使用提供商特定的 API,那么工作就非常简单了。示例示例

要独立于提供商,请尝试以下任何技巧......

身份生成器持有者

public abstract class IdGeneratorHolder {
    /* PersistentEntity is a marker interface */
    public static IdGenerator getIdGenerator(Class<? extends PersistentEntity> entityType) {
             /* sample impelementation */
        if(Product.class.isAssignableFrom(entityType)) {
            return new ProductIdGenerator();

        }
        return null;
    }
}

通用 IdGenerator 接口

public interface IdGenerator {
    String generate();
}

Specific IdGenerator - 产品 ID 生成器

public class ProductIdGenerator implements IdGenerator {
    public String generate() {
            /* some complicated logic goes here */
        return ${generatedId};
    }
}

现在设置生成的 id在无参构造函数中 OR 在@PrePersist方法中.

产品.java

public class Product implements PersistentEntity {

    private String id;

    public Product() {
        id = IdGeneratorHolder.getIdGenerator(getClass()).generate();
    }

    @PrePersist
    public void generateId() {
        id = IdGeneratorHolder.getIdGenerator(getClass()).generate();
    }

}

在上面的示例中,所有 id 都是同一类型,即java.lang.String。如果持久化实体有不同类型的id......

IdGenerator.java

public interface IdGenerator {
    CustomId generate();
}

自定义Id.java

   public class CustomId {

    private Object id;

    public CustomId(Object id) {
        this.id = id;
    }

    public String  toString() {
        return id.toString();
    }
    public Long  toLong() {
        return Long.valueOf(id.toString());
    }
}

项目.java

@PrePersist
    public void generateId() {
        id = IdGeneratorHolder.getIdGenerator(getClass()).generate().toLong();
    }

您还可以使用自定义注释...

CustomIdGenerator.java

public @interface CustomIdGenerator {
    IdStrategy strategy();
}

IdStrategy.java

  enum IdStrategy {
        uuid, humanReadable,    
    }

IdGeneratorHolder.java

public abstract class IdGeneratorHolder {
    public static IdGenerator getIdGenerator(Class<? extends PersistentEntity> entityType) {
        try { // again sample implementation
            Method method = entityType.getMethod("idMethod");
            CustomIdGenerator gen = method.getAnnotation(CustomIdGenerator.class);
            IdStrategy strategy = gen.strategy();
            return new ProductIdGenerator(strategy);
        }

还有一件事......如果我们在@PrePersist方法中设置id,equals()方法不能依赖id字段(即代理键),我们必须使用business/natural key来实现equals()方法。但是,如果我们在无参数构造函数中将 id 字段设置为某个唯一值(应用程序中唯一的 uuid 或“app-uid”),它可以帮助我们实现 equals() 方法。

public boolean equals(Object obj) {
        if(obj instanceof Product) {
            Product that = (Product) obj;
            return this.id ==that.id;
        }
        return false;
    }

如果我们或其他人(有意或无意)多次调用@PrePersist 注解的方法,“唯一的 id 将被更改!!!”因此在无参数构造函数中设置 id 是更好的选择。或者为了解决这个问题,进行非空检查......

  @PrePersist
    public void generateId() {
        if(id != null)
            id = IdGeneratorHolder.getIdGenerator(getClass()).generate();
    }
}

UPDATE

如果我们将 id 生成放在 无参数构造函数,不是吗 加载实体时出现问题 从数据库中?因为冬眠 将调用无参数构造函数 导致现有的 id 成为 重新生成

是的,你是对的,我错过了那部分。 :( 实际上,我想告诉您:- 在我的应用程序中,每个实体对象都与一个组织实体相关联;因此我创建了一个带有两个构造函数的抽象超类,并且每个实体(组织除外)都扩展了该类。

    protected PersistentEntityImpl() {
    }

    protected PersistentEntityImpl(Organization organization) {
        String entityId = UUIDGenerator.generate();
        String organizationId = organization.getEntityId();
        identifier = new EntityIdentifier(entityId, organizationId);
    }

无参数构造函数适用于 JPA 提供者,我们从不调用无参数构造函数,而是调用其他基于组织的构造函数。如你看到的。 id 在基于组织的构造函数中分配。 (我在写答案时真的错过了这一点,对此感到抱歉)。

看看您是否可以在您的应用程序中实施此或类似的策略。

第二个选项是使用 @PrePersist 注释。我把它放进去 并且该方法从未被击中并给出 我是一个例外,说明我需要 手动设置id。有没有 我还应该做些什么?

理想情况下,JPA 提供程序应在持久化实体对象之前调用 @PrePersist 方法(在类中声明的方法以及在超类中声明的所有其他方法)。除非您显示一些代码和控制台,否则无法告诉您出了什么问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将自定义标识符分配给 @id 属性 的相关文章

随机推荐

  • 从批处理文件中解析 XML 文件的属性

    我正在解析一个 XML 文件 如下所示
  • 初始化本地数据存储异常:没有为此线程注册API环境

    我想使用一些数据来初始化我的本地数据存储 常规Java程序 我不想启动开发服务器 并调用服务 servlet 我收到以下异常 例外 Exception in thread main java lang NullPointerExceptio
  • 无法连接 github.com 端口 443:操作超时

    git clone https github com RubyLouvre avalon Cloning into avalon fatal unable to access https github com RubyLouvre aval
  • req.cookies 返回未定义但 cookie 已设置

    我在用cookie parser在我的 Express 应用程序中 当请求根页面时 我使用以下命令在 cookie 上设置一个随机数res cookie name value 它设置得很好 我检查了我的浏览器控制台 但是当我尝试登录时req
  • 自动以正确的编码打开文件[重复]

    这个问题在这里已经有答案了 我正在处理一些有关编码的文件中的一些问题 我们收到其他公司的文件并必须阅读它们 文件为 csv 格式 奇怪的是 这些文件似乎是用 UTF 16 编码的 我设法做到这一点 但我必须使用codecs模块并指定编码 这
  • 如何在1个viewController中管理2个tableview?

    有谁知道一种在一个 viewController 中管理多个 tableView 的简单方法 到目前为止我是这样做的 NSInteger numberOfSectionsInTableView UITableView tableView i
  • 如何使用 png-brush 和 UIBezierPath 擦除 UIImageView 的一部分

    我有两个 UIImageView 第一个在第二个之上 我想用画笔擦除第一张图像的一部分 画笔是具有软边缘的 png 图片 以使第二张图像的一部分可见 我是通过这种方式做到的 1 触摸移动 and self setNeedsDisplayIn
  • 为什么在使用 Google Protocol Buffers 时会看到“无法导入名称描述符_pb2”错误?

    当使用 protobuf 类生成的 Python 代码时 我们收到以下错误 cannot import name descriptor pb2 等效的 C 生成的代码运行得很好 因此看起来我们的实际原型定义没有问题 当我尝试导入我们的类时
  • 在 Android 中以编程方式发送电子邮件

    所以我尝试在 Android 中发送电子邮件而不使用 Intent 因为我需要它在后台发送 我正在关注这个帖子 我已将 jar 添加为构建路径的一部分 我有这个代码作为类 package cistoran partyPlanner impo
  • `<>` 的 `>` 处出现意外标记

    我正在努力追随React 井字游戏教程在我当地的环境中 然而 当我跑步时npm start 我遇到语法错误 lt gt 如何重现 在教程中间的 此时您的代码应如下所示 下 单击示例代码右上角的 分叉 其中将 1 到 9 的数字写在表格中 单
  • 2.23:应用程序必须遵循 iOS 数据存储指南,否则将被拒绝 [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 通过将应用程序上传到应用程序商店给了我这个错误 2 23 应用程序必须遵循iOS数据存储指南 否则将被拒绝 我一直在观察问题是我正在使用的文件之一不满足存储要求 更具体地说 它是
  • 如何处理浏览器多选项卡中的用户注销?

    我正在使用 codeigniter 会话来存储用户登录信息 当用户在多个选项卡中打开时 在一个选项卡中注销时 我希望在用户访问其他选项卡时自动刷新页面 这可能吗 刚刚测试了一下 我能看到的最简单的方法 似乎至少在 Chrome 中有效 但可
  • 如何修复 JSX 表达式必须有一个父元素?

    我正在尝试在本机反应中切换模态 平面列表中的每个项目都应该有一个切换选项来打开模式 我收到错误 JSX 表达式必须有一个父元素 我试图用谷歌搜索正确的语法 但找不到解决方案 class CategoriesScreen extends Co
  • jquery 无法读取未定义的属性“done” - 避免这种情况

    我有一个返回结果 或不返回结果 的函数 问题是当它不返回任何值时我在控制台中收到消息 无法读取未定义的属性 完成 这是真的 我确实理解这个问题 另外 此错误不会使我的代码停止工作 但我想知道是否有机会避免这种情况 ajax中的函数是 fun
  • 使用 angularJS 的表单上的空操作属性

    我试图在 AngularJS 应用程序中以正常方式提交表单 但遇到一个问题 似乎我必须指定操作属性 根据 HTML 规范 http www whatwg org specs web apps current work multipage a
  • 与给定表或视图有关系的所有表的列表

    在 SQL Server 中 是否有命令返回与给定表或视图有关系的所有表的列表 编辑 SQL Server 2008 对于 SQL Server 2005 及更高版本 请使用以下内容 SELECT name OBJECT NAME pare
  • Java 8 相当于 Streams 的 getLineNumber()

    Java 8 中的 Streams 是否有与 getLineNumber 等效的方法 我想在文本文件中搜索单词并将行号作为整数返回 这是我的搜索方法 result Files lines Paths get fileName filter
  • 澄清 Ingress 负载均衡器

    我不确定负载平衡如何与 Ingress 配合使用 如果我理解正确的话 发生的事情实际上是这样的 我看不到负载平衡是如何执行的 我上面画的方案有什么问题吗 你能帮我纠正一下吗 Notes 以下答案告诉我入口控制器本身是 负载均衡器 类型 入口
  • 3 种颜色之间的颜色插值

    我使用以下方程获得从 colorA 到 colorB 的漂亮颜色渐变 但我不知道如何对 3 种颜色执行相同的操作 因此渐变从 colorA 到 colorB 到 colorC colorT colorA p colorB 1 0 p 其中
  • 将自定义标识符分配给 @id 属性

    我正在将遗留系统迁移到使用 Hibernate 3 它当前生成自己的标识符 为了在尝试将系统转移到更好的系统之前保持系统当前的功能 我将如何指定 使用注释 我自己的类 该类将在发生插入时返回自定义生成的标识符 就像是 Id CustomId