Hibernate独特的密钥生成器

时间:2013-07-19 11:57:27

标签: java hibernate uniqueidentifier

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

    protected String licenceKey;

我必须生成一个唯一的20-char Key作为该字段的值,它必须是使用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;
}

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

UPDATE:

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

1 个答案:

答案 0 :(得分:0)

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

此外,在您的代码中,问题在于您自己检查唯一性。你应该把它留给DB。您可能希望阅读" Unique"约束。基本上它意味着它不是主键,但它在所有其他行中仍然是唯一的。

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

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

2)如何使该密钥唯一?

要使密钥唯一,请使用提供的数据库" Unique"约束。如果您正在使用休眠,则可以在字段上方使用此字段' 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.
}