当前位置: 首页 > 面试题库 >

使用MySQL和Oracle进行Hibernate自动密钥生成

邵劲
2023-03-14
问题内容

我正在使用 Java 应用程序,该应用程序应该在具有相同数据库架构的两个不同数据库上执行CRUD操作(使用 Hibernate
4.3.8)。有一个 MySQL (版本5.1.73)和一个 Oracle (11g Express
Edition版本11.2.0.2.0-64位)数据库。

使用Hibernate Code Generation从数据库表中生成带有 JPA批注的 Java类。

问题在于,我们现在需要使用自动主键生成,而MySQL使用 GenerationType.IDENTITY, 而Oracle使用
GenerationType.SEQUENCE 。此外,在极少数情况下,我们需要能够自行手动设置主键。

带注释的类中的followig代码可为两个数据库自动生成密钥,但如果主键是自设置的,则失败。

@GeneratedValue(strategy=GenerationType.AUTO, generator="sequence_generator")
@SequenceGenerator(name="sequence_generator", sequenceName="SEQUENCE1")
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
    return this.id;
}

没有 @GeneratedValue@SequenceGenerator 批注,可以手动设置主键,但是自动生成无效。


问题答案:

即使您使用时GenerationType.AUTO没有任何SEQUENCE特定参数,也将无法保存分配的标识符。

如果您愿意做出一些妥协,则有一些解决方法:

  1. 一种方法是切换到分配的标识符。您可以使用适用于MySQL和Oracle的UUID标识符,也可以手动分配值。

  2. 另一种方法是使用自定义表生成器。

首先,您定义一个可识别的接口:

    public interface Identifiable<T extends Serializable> {
    T getId();
}

然后扩展表生成器:

    public class AssignedTableGenerator extends TableGenerator {

    @Override
    public Serializable generate(SessionImplementor session, Object obj) {
        if(obj instanceof Identifiable) {
            Identifiable identifiable = (Identifiable) obj;
            Serializable id = identifiable.getId();
            if(id != null) {
                return id;
            }
        }
        return super.generate(session, obj);
    }
}

此生成器能够将分配的标识符与合成的生成的标识符混合:

    doInTransaction(session -> {
    for (int i = 0; i < 5; i++) {
        session.persist(new AssignTableSequenceIdentifier());
    }
    AssignTableSequenceIdentifier tableSequenceIdentifier = new AssignTableSequenceIdentifier();
    tableSequenceIdentifier.id = -1L;
    session.merge(tableSequenceIdentifier);
    session.flush();
});

生成以下语句:

    select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
insert into sequence_table (sequence_name, next_val)  values (default,1)
update sequence_table set next_val=2  where next_val=1 and sequence_name=default
select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
update sequence_table set next_val=3  where next_val=2 and sequence_name=default
select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
update sequence_table set next_val=4  where next_val=3 and sequence_name=default
select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
update sequence_table set next_val=5  where next_val=4 and sequence_name=default
select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
update sequence_table set next_val=6  where next_val=5 and sequence_name=default
select identityvs0_.id as id1_0_0_ from assigneTableIdentifier identityvs0_ where identityvs0_.id=-1
insert into assigneTableIdentifier (id) values (1, 2)
insert into assigneTableIdentifier (id) values (2, 4)
insert into assigneTableIdentifier (id) values (5, -1)

对于Oracle,您可以结合SEQUENCE和分配的生成器,如本文所述。

简而言之,请考虑以下生成器:

public class AssignedSequenceStyleGenerator 
    extends SequenceStyleGenerator {

    @Override
    public Serializable generate(SessionImplementor session, 
        Object obj) {
        if(obj instanceof Identifiable) {
            Identifiable identifiable = (Identifiable) obj;
            Serializable id = identifiable.getId();
            if(id != null) {
                return id;
            }
        }
        return super.generate(session, obj);
    }
}

您可以将其映射到您的实体,如下所示:

@Id
@GenericGenerator(
    name = "assigned-sequence",
    strategy = "com.vladmihalcea.book.hpjp.hibernate.identifier.AssignedSequenceStyleGenerator",
    parameters = @org.hibernate.annotations.Parameter(
        name = "sequence_name", 
        value = "post_sequence"
    )
)
@GeneratedValue(
    generator = "assigned-sequence", 
    strategy = GenerationType.SEQUENCE
)
private Long id;

所有代码都可以在GitHub上使用,并且像一个超级按钮一样工作。



 类似资料:
  • 带注释的类中的followig代码可用于两个数据库的自动键生成,但如果主键是自设置的,则会失败。 如果没有@GeneratedValue和@SequenceGenerator注释,则可以手动设置主键,但自动生成无法工作。

  • 问题内容: 我正在使用Java应用程序,该应用程序要求我使用从不同字符串生成的两个密钥进行加密和解密。一个字符串来自用户,另一个是主密钥。我上网查看了有关它的一些参考资料。我真的很想知道如何实现此目标。我将展示我现在拥有的。 因此,从代码中可以看到,我使用了其他stackoverflow帖子中的一些代码,并对其进行了一些修改。我只是不知道如何从2个字符串生成2个密钥,以及从哪里可以获取用于解密的S

  • 我正在开发一个Java应用程序,它要求我使用从不同字符串生成的两个密钥进行加密和解密。一个字符串来自用户,另一个是主密钥。我在网上查了一下,找到了一些关于它的参考资料。我真的很想得到一些帮助,了解如何实现这一点。我将展示我现在所拥有的。 正如您从代码中看到的,我使用了其他stackoverflow帖子中的一些代码,并对其进行了一些修改。我只是不知道如何从2个字符串生成2个密钥,以及从哪里可以获得用

  • 我已经看到了其他一些关于创建加密的初始化向量(IV)的问题,似乎使用随机值是一种选择。然而,我需要生成用于解密的IV,所以我必须使用基于一些salt的数据加密的相同的数据。 node.js加密函数createDecipher表示: crypto.createdecipher()的实现使用OpenSSL函数EVP_BytesToKey派生密钥,摘要算法设置为MD5,一次迭代,没有salt。 好的,听

  • 我正在使用Spring MVC Hibernate 在保存新记录时,会生成自动递增的新主键(db.MySQL)。我想获取并返回与上述方法相关的新的自动递增值。 更新我!

  • 我想生成一个自签名的可信证书和一个csr,并用创建的可信证书对csr进行签名。我正在用keytool尝试它。在使用以下命令创建受信任证书的第一步中 keytool-list-v-keystore cert/test.keystore 使用上面的“genkey”命令创建的证书的条目类型为“privatekeyentry”,如何创建可信的证书条目?