具有 SQL Server 2022 序列的 JPA 实体 ID 字段

问题描述 投票:0回答:1

我正在尝试将 Spring Boot 服务连接到 SQL Server 2022 数据库,但我遇到了序列问题:

public class SomeEntity {
    @Id
    @SequenceGenerator(name = "some_seq", schema = "sch_some", sequenceName = "some_seq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "some_seq")
    @Column(name = "id", columnDefinition = "decimal")
    private Long id;
    ...
}

这是我尝试在表中存储某些内容时遇到的错误:

{“日期”:“2024-07-07T20:50:08,250Z”,“env”:“测试”,“应用程序”:“某些服务”,“版本”:“1.32.0”,“主机” :"_","level":"错误","logger":"org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet]","msg":" servlet [dispatcherServlet] 在上下文 [] 中的 Servlet.service() 抛出异常 [请求处理失败;嵌套异常是 org.springframework.dao.InvalidDataAccessResourceUsageException:执行独立工作时出错 [n/a]; .hibernate.exception.SQLGrammarException:执行隔离工作时出错],其根本原因","thread":"http-nio-8080-exec-1","context":[],"eventId":"com.microsoft.sqlserver .jdbc.SQLServerException","stack":"com.microsoft.sqlserver.jdbc.SQLServerException: 无效的对象名称“some_db.sch_some.some_seq”。 在 com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:262) 在 com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1624) 在com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:594) 在 com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:524) 在 com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7194) 在 com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2979) 在 com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:248) 在com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:223) 在com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:446) 在com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52) 在com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java) 在

这是我创建序列的方法

create sequence SCH_SOME.SOME_SEQ start with 1 increment by 1;

由于我在这个模式中有另一个表没有插入问题,我认为这可能是访问问题。我还尝试运行 grant select 语句,就像在 Oracle 中一样,但我最终得到了这个

SQL 错误 [4606] [S0001]:授予或撤销的权限 SELECT 与对象不兼容。

那么在 SQL Server 中,是否还需要另一组权限来运行授予?我也尝试过 UPDATE 和 ALTER,但这并没有什么区别。如果有人能够阐明这个问题,我们将不胜感激。谢谢。

更新 - 我做了一些调试,发现这就是 Hibernate 生成的:

Hibernate: 
    select
        next_val as id_val 
    from
        some_db.sch_some.some_seq with (updlock,
        rowlock)

我认为这不是 SQL Server 的正确语法。

java sql sql-server jpa spring-data-jpa
1个回答
0
投票

您看到的错误消息是由于 Hibernate 尝试以 SQL Server 不支持的方式使用序列所致。在 SQL Server 中,序列不是作为表访问的,而是通过函数调用访问的。 从 SQL Server 中的序列获取下一个值的正确语法是

NEXT VALUE FOR sequence_name
。但是,Hibernate 生成 SQL 语句时就好像该序列是一个表,这对于 SQL Server 来说是不正确的。 要解决此问题,您可以使用
@TableGenerator
注释代替
@SequenceGenerator
@TableGenerator
注释是一种生成标识符的可移植方法,它适用于不支持序列的数据库,例如 SQL Server。 以下是如何修改代码的示例:

@Id
@TableGenerator(name = "some_gen", table = "id_gen", pkColumnName = "gen_name", valueColumnName = "gen_val", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.TABLE, generator = "some_gen")
@Column(name = "id", columnDefinition = "decimal")
private Long id;

在上面的代码中,

id_gen
是Hibernate将用来生成ID的表。该表应有两列:
gen_name
gen_val
gen_name
列存储生成器的名称,
gen_val
列存储 ID 的当前值。 请注意,您需要在数据库中手动创建
id_gen
表。以下是如何做到这一点的示例:

CREATE TABLE id_gen (
    gen_name VARCHAR(255) NOT NULL,
    gen_val BIGINT NOT NULL,
    PRIMARY KEY (gen_name)
);

创建表后,您需要为生成器插入一行:

INSERT INTO id_gen (gen_name, gen_val) VALUES ('some_gen', 0);

这应该可以解决您面临的问题。

© www.soinside.com 2019 - 2024. All rights reserved.