Hibernate 模式参数在 @SequenceGenerator 注释中不起作用

Posted

技术标签:

【中文标题】Hibernate 模式参数在 @SequenceGenerator 注释中不起作用【英文标题】:Hibernate schema parameter doesn't work in @SequenceGenerator annotation 【发布时间】:2011-02-06 01:45:37 【问题描述】:

我有以下代码:

@Entity
@Table(name = "my_table", schema = "my_schema")
@SequenceGenerator(name = "my_table_id_seq", sequenceName = "my_table_id_seq", 
                   schema = "my_schema")
public class MyClass 
    @Id
    @GeneratedValue(generator = "my_table_id_seq", 
                    strategy = GenerationType.SEQUENCE)
    private int id;


数据库:Postgresql 8.4,Hibernate annotations 3.5.0-Final。

保存 MyClass 的对象时,它会生成以下 SQL 查询:

select nextval('my_table_id_seq')

因此没有架构前缀,因此无法找到序列。当我写像

这样的 sequenceName
sequenceName = "my_schema.my_table_id_seq"

一切正常。

我对架构参数的含义有误解还是错误?任何想法如何使架构参数工作?

【问题讨论】:

我在这里遇到了同样的问题,并将架构放在序列名称上,就像你做的那样。我的 @SequenceGenerator 没有架构属性。 【参考方案1】:

这里有同样的问题,对我来说似乎是一个错误。我正在使用休眠 3.6.7 查看源代码,我看到了一个方法org.hibernate.cfg.annotations.reflection.JPAOverridenAnnotationReader#buildSequenceGeneratorAnnotation(Element element),它似乎复制了namesequence-nameinitial-valueallocation-sizeattributes 的值,但我看不到对catalogschema的引用

我希望看到类似于方法getTable(Element tree, XMLContext.Default defaults)(属于同一类)的东西,它具有

annotation.setValue("schema", table.schema());
annotation.setValue("catalog", table.catalog());` 

buildTableGeneratorAnnotation

copyStringAttribute(ad, element, "catalog", false);
copyStringAttribute(ad, element, "schema", false);

所以,即使有点老套,至少对于这个版本来说,就像你说的那样,似乎是在 sequenceName 前面加上前缀。

【讨论】:

【参考方案2】:

我的解决方法如下所示(JPA 2.1、Hibernate 4.3.8.Final、PostgreSQL 9.4):

@SequenceGenerator(name = "seq_name", sequenceName = "my_schema.seq_name", schema = "my_schema", allocationSize = 1, initialValue = 1)

【讨论】:

【参考方案3】:

我在 postgresql 9.6 中通过仅在序列名称前添加我的架构解决了这个问题,如下所示:

(before) sequence name: seq_area_tematica
(after) sequence name: sisbp.seq_area_tematica

及其作品。见代码:

@Id
@Column(name="seq_area_tematica")
@GeneratedValue(generator="sequence",strategy=GenerationType.SEQUENCE) 
@SequenceGenerator(name="sequence",sequenceName="sisbp.seq_area_tematica")
private Long id;

参见序列名称前的“sisbp”。 sequenceName 是“seq_area_tematica”,现在是“sisbp”(模式)+“seq_area_tematica”。

【讨论】:

【参考方案4】:

在这里使用 Hibernate 4.2.0.Final 并有同样的问题。看起来这是另一个用户回答的错误。我想为序列使用动态模式,具体取决于为会话设置的模式,但对于某些序列,我想使用public 模式。所以对我来说,我不得不使用你提出的解决方案:将模式名称放在我想使用特定模式的序列名称上:

@SequenceGenerator(name = "my_table_id_seq", sequenceName="my_schema.my_table_id_seq",
 schema = "my_schema")

对于我想为会话使用架构集的情况,我使用了sequenceName,而没有预先设置架构。

对于那些希望所有序列都使用相同架构的人,您可以使用hibernate.default_schema 属性。这样您就无需更改 @SequenceGenerator 属性:

<prop key="hibernate.default_schema">my_schema_name</prop>

我正在使用 PostgreSQL DBMS。如果您想在 Hibernate 调用 nextval('my_sequence') 时动态更改序列的名称,您可以扩展您的数据库方言类并配置 Hibernate 以使用。您只需要覆盖 getSequenceNextValString() 方法。提供给该方法的唯一信息是在@SequenceGenerator 上定义的sequenceName 属性:

public class SchemaPostgreSQLDialect extends PostgreSQL82Dialect 
    @Override
    public String getSequenceNextValString(String sequenceName) 
        String seqFinalName = mySequenceNameModifierMethod(sequenceName);       
        return "select nextval('" + seqFinalName + "')";
    

    private String mySequenceNameModifierMethod(String originalSequenceName) 
        // magic modification here
        return modifiedSequenceName;
    

我没有使用最后一种方式来更改序列的名称,因为它似乎不太适合我的情况。

【讨论】:

【参考方案5】:

这听起来像是一个错误:JPA 提供程序应该尊重 @SequenceGenerator 注释的“新”(自 Java Persistence 2.0 起)schemacatalog 属性。我建议提出a Jira issue(注解和实体管理器项目现在都在核心下),找不到任何现有的。

【讨论】:

【参考方案6】:

同样的问题,在 Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 上使用 Hibernate 4.3.6.Final 和 Spring 4.1.4.RELEASE。

看起来这是一个错误 => https://hibernate.atlassian.net/browse/HHH-7232

我们通过在模式 A 中创建一个指向模式 B 中的序列的同义词来解决这个问题。这个同义词是我们在 @SequenceGenerator 注释的模式属性中使用的

【讨论】:

据称已在 5.x 版本中修复:hibernate.atlassian.net/browse/…【参考方案7】:

嗯,我不太喜欢使用 hibernate 的内部结构,但这里有一些信息:

https://forum.hibernate.org/viewtopic.php?p=2406761

您还可以为通过 ALTER USER ... SET SEARCH_PATH 连接到 PostgreSQL 的用户设置默认架构

【讨论】:

【参考方案8】:

尝试将SequenceGenerator 注释从POJO 的类声明移至id 字段声明。使用 Hibernate 3.6.4 这个

@Entity
@Table(name = "my_table", schema = "my_schema")
public class MyClass 
    @Id
    @GeneratedValue(generator = "my_table_id_seq", 
                strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(name = "my_table_id_seq", sequenceName = "my_table_id_seq", schema = "my_schema")
    private int id;


mysql 生成这个

create table my_schema.my_table_id_seq (
     next_val bigint 
);

insert into my_schema.my_table_id_seq values ( 1 );

这适用于 PostgreSQL

create sequence my_schema.my_table_id_seq start 1 increment 50;

【讨论】:

【参考方案9】:

在我的情况下,执行不会通过@jambriz 指示的位置。

版本:Hibernate 3.6.10.Final

hibernate.id.new_generator_mappings = falsepersistence.xml 时出现问题。当设置为true 或简单地删除时,Hibernate 使用序列方案来构建 SQL。 解决方案:

<property name="hibernate.id.new_generator_mappings" value="true" />
<!-- Or remove this property -->

代码哪里出了问题?

在第 445 行和第 480 行之间的 AnnotationBinder.java 类中。在第 455 行的 if 块中,您可以看到正在设置的方案。在 else 中没有设置方案。

希望这会有所帮助!

【讨论】:

【参考方案10】:

当使用带有弹簧的休眠时 请设置

<prop key="hibernate.id.new_generator_mappings">true</prop>

【讨论】:

【参考方案11】:

你好,我遇到了同样的问题

但将您的 hibernate.hbm2ddl.auto 设置为更新并运行。

<property name="hibernate.hbm2ddl.auto">update</property>

【讨论】:

我知道这是事后诸葛亮,但这个答案是不正确的,因为它只会在默认模式中创建生成器,这可能不是你想要的。

以上是关于Hibernate 模式参数在 @SequenceGenerator 注释中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

模式验证:缺少表 [hibernate_sequences]

在 Hibernate 中使用 SEQUENCE 时导致唯一约束违规的原因是啥?

缺少序列或表:hibernate_sequence

如何解决异常:表 'DBNAME.hibernate_sequence' 不存在

未找到“HIBERNATE_SEQUENCE”

GeneratedValue 无法识别现有的 hibernate_sequence