0

在我的模型中,我有一个带有该字段的实体购买

    protected String licenceKey;

我必须生成一个唯一的 20 字符密钥作为该字段的值,并且它必须是使用 SecureRandom 生成的唯一值。我尝试使用 IdentifierGenerator 接口,但它不起作用,我不明白如何检查该值是否已经存在并在这种情况下强制生成另一个键。

@Override
public Serializable generate(SessionImplementor session, Object object) 
    throws HibernateException {

    String key;
    Purchase existingPurchase;
    do {
        key = (RandomStringUtils.random(20, 0, 0, true, true, null, 
            new SecureRandom())).toUpperCase();
        existingPurchase = new PurchaseDao().getProductByLicenceKey(key);
    } while (existingPurchase != null);
    return key;
}

这是实现这一目标的正确方法吗?我的错误是什么?

更新:

现在我设法使用此代码并生成正确的许可证密钥。但因此我必须将 licenceKey 注释为 @Id - 否则它不会生成任何密钥。如何克服这个问题并强制 Hibernate 为非 ID 字段生成密钥?

4

1 回答 1

0

首先,您的代码使用@Id 的原因是,现在序列键是您的主键,如果数据库看到两行具有相同的主键,则会抛出错误;在您的情况下,相同的序列号。

此外,在您的代码中,事情是您自己检查唯一性。你应该把它留给数据库。您可能想阅读“唯一”约束。基本上这意味着它不是主键,但它在所有其他行中仍然是唯一的。

现在。您的问题有两个部分:1)如何生成包含 20 个字符的唯一密钥?

要生成一个安全的唯一密钥,您可以尝试几个框架。OpenSSL 是我所知道的最好的一个。有几个教程可以让您了解如何在 Java 中使用 openssl。

2)如何使该密钥独一无二?

要使键唯一,请使用数据库提供的“唯一”约束。如果您使用的是休眠,您可以在您的字段“licenceKey”上方使用它:

@Column(name="licence_key" unique="true"
protected String licenceKey;

如果您使用的是普通 Java,那么您可以转到您的数据库,并在那里添加唯一键约束。例如在 MySQL 中,命令是:

alter table <table_name> add unique(<column_name>);

现在,当您将在数据库中插入键时,数据库将检查该键是否已经存在。如果没有,它将添加该密钥。如果密钥存在,那么它将引发错误。

因此,在您的代码中,您需要这样做:

try {
    //insert your row here. If the exception will be thrown, then you can catch that in the catch block.
} catch(Exception e) {
    //catch the exception here.
} finally {
    //do something here.
}
于 2014-04-19T04:55:29.213 回答