我有一个表,其中有一个简单的int-id列,在SQL Server中标识自动递增。
实体的Id用@Id
和@GeneratedValue
注释
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", length = 4, precision = 10, nullable = false)
private Integer id;
在SQL Server中,列被正确设置为标识,Seed
和Increment
等于1。
当我试图持久化这个实体的一个实例时,Hibernate会尝试查询Hibernate_sequence表以获取ID值。由于我没有在模式中创建该表,所以出现了一个错误:
无法读取高值:com。微软sqlserver。jdbc。SQLServerException:对象名“MySchema”无效。Hibernate\u序列'
如果我将generation type更改为IDENTITY,那么一切都会按预期进行
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", length = 4, precision = 10, nullable = false)
private Integer id;
我不能这样更改,因为我的应用程序将同时在MS SQL和ORACLE上运行,后者不支持自动递增列。
据我所知,如果基础数据库支持自动增量行为,自动类型应该使用自动增量行为,所以我不知道为什么不工作。
更新:
我花了一些时间,但我能够准确地理解发生了什么。
我正在使用具有以下行为的遗留数据库:
以下是使用一些id生成策略的结果:
所以我需要弄清楚的是一种配置实体的方法:
当我需要插入依赖于主实体的实体(通过外键)时,这可能会在Oracle上造成严重问题,因为Hibernate不知道“外部”触发器生成了哪个ID值。
是因为
@GeneratedValue(策略=GenerationType.AUTO)
在早期版本中,默认情况下使用SequenceStyleGenerator
你得看看这个https://hibernate.atlassian.net/browse/HHH-11014
Orcale 12c支持IDENTITY,SQLSERVER 2012支持SEQUENCES。我相信序列总是比身份更好的选择。IDENTITY禁用批处理,SEQUENCES允许您提供优化器,例如pooled-lo优化策略。
以下是为配置的GenerationType值选择实际标识符生成器的方式:
switch ( generatorEnum ) {
case IDENTITY:
return "identity";
case AUTO:
return useNewGeneratorMappings
? org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName()
: "native";
case TABLE:
return useNewGeneratorMappings
? org.hibernate.id.enhanced.TableGenerator.class.getName()
: MultipleHiLoPerTableGenerator.class.getName();
case SEQUENCE:
return useNewGeneratorMappings
? org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName()
: "seqhilo";
}
>
如果使用新的标识符生成器:
财产。put(“hibernate.id.new_generator_mappings”,“true”);
AUTO实际上将使用序列样式生成器,如果数据库不支持序列,您最终将使用表生成器来代替(这是一个可移植的解决方案,但它的效率低于IDENTITY或SEQUENCE)。
如果您使用遗留标识符生成器,那么您最终会使用“本机”生成策略,这意味着:
public Class getNativeIdentifierGeneratorClass() {
if ( supportsIdentityColumns() ) {
return IdentityGenerator.class;
}
else if ( supportsSequences() ) {
return SequenceGenerator.class;
}
else {
return TableHiLoGenerator.class;
}
}
如果要添加一个新的Oracle12gDialect,并且它将支持标识,那么AUTO可能会切换到标识而不是顺序,这可能会打破您当前的预期。目前还没有这样的方言,所以在Oracle上你有序列,在MSSQL上你有身份。
结论:
试着这样做:
@Id
@GenericGenerator(name = "native_generator", strategy = "native")
@GeneratedValue(generator = "native_generator")
private Long id;
如果您的遗留系统使用表来生成序列值,并且没有使用过Hilo优化,您可以使用表标识符生成器:
@Id
@GeneratedValue(generator = "table", strategy=GenerationType.TABLE)
@TableGenerator(name = "table", allocationSize = 1
)
private Long id;
您也可以使用JPA表生成器,只要确保配置了正确的优化器。更多信息查看我的Hibernate教程
我有一个类似的问题,发现了这个信息(在这里有更深入的解释)。
将此属性添加到我的persistence.xml文件中修复了问题:
<property name="hibernate.id.new_generator_mappings" value="false" />
问题内容: 我有多个结构相同的数据库,有时会在其中复制数据。为了保持数据完整性,我使用两列作为主键。一个是数据库ID,它链接到包含有关每个数据库的信息的表。另一个是表键。它不是唯一的,因为它可能有多个行,且此值相同,但database_id列中的值不同。 我打算将这两列变成一个联合主键。但是,我也想将表键设置为自动递增-但基于database_id列。 EG,使用以下数据: 如果我要添加包含dab
问题内容: 使用Postgres,我试图用SQL自动编号主键。但是,这给了我一个错误。 错误: 知道为什么吗? 问题答案: Postgres 10或更高版本 列(请参见下文)保持不变。但是考虑一个 专栏。Postgres10实现了此标准SQL功能。 手册中的基本语法和信息。 __用列 创建 表 将 列 添加 到现有表 表可能填充也可能不填充行。 同时使它成为PK(表还不能拥有PK): 有关的: 如
这就是我所拥有的 当程序运行时,会出现一个添加新类别的屏幕,用户必须写入类别的名称和描述,但ID应该是自动的,并且应该在每次用户输入新类别时增加ID。我这样做并没有达到预期效果,它只增加了一次,但由于初始值保持在5,所以它总是6。
问题内容: 我刚遇到一个我无法解决的问题。 我有一个用作队列的数据库表,我在其中存储一些记录。处理记录后,它们将被删除。删除是由Rails构建在一个触发MySql数据库的循环中调用的。 但是现在我注意到,在表中将 autoIncrement Id (主键)设置回 1 。(这损坏了我在审计表中的引用。相同记录现在指向多个不同的项目队列) 我不使用或删除表构造,而是在代码中再次创建它。 是否有人遇到像
问题内容: 我正在尝试在mysql数据库中创建一列,该列自动递增1但从0-Z开始然后滚动。 例如000、001、002,…,009、00A,00B,…,00Z,010,…,0ZZ,…,100。 我想让数据库通过自动递增字段创建列。 我的想法是: 为从0到36的每个字符创建一列,然后将行N(其中N是最低有效数字)自动递增1。然后在每列上添加触发器,以在第N列达到36时向N-1列添加1 。 创建一个包
问题内容: 我有下面的SQL,我正在尝试使用它创建一个表和一些列。作为它的一部分,我希望其中两列自动递增一个整数。当我尝试使用以下代码时,它给我一个错误。 当我从SQL中删除关键字“ AUTOINCREMENT”时,它可以正常工作。 是否可以有两个自动增量列?如果不是,是否有办法让一列在插入时自动从另一列(自动递增)中获取值? 谢谢 问题答案: 您不能有两个自动增量字段。您应该使用一个自动增量字段