java 休眠序列生成器的对象名称无效

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28234366/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 13:13:51  来源:igfitidea点击:

Invalid Object Name for Hibernate Sequence Generator

javadatabasehibernatesql-server-2012sequence-generators

提问by lassekokholm

I am developing an application that accesses a database running SQL Server 2012 through the Hibernate framework. However, I cannot figure out how to make an instance of the SequenceGenerator annotation work; I get an exception whenever I attempt to save a new object instance to my database table. The class to be saved is the following:

我正在开发一个应用程序,它通过 Hibernate 框架访问运行 SQL Server 2012 的数据库。但是,我无法弄清楚如何使 SequenceGenerator 注释的实例起作用;每当我尝试将新对象实例保存到我的数据库表时,都会出现异常。要保存的类如下:

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name="MESSAGES")
public class Message implements Serializable {

    private static final long serialVersionUID = -3535373804021266134L;

    @Id
    @Column(name="MESSAGE_ID")
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="MESSAGE_GEN")
    @SequenceGenerator(name="MESSAGE_GEN", sequenceName="MESSAGE_SEQ", initialValue=1, allocationSize=1) 
    private Long id;

    @Column(name="TEXT")
    private String text;

    public Message(String text) { 
        this.text = text;
    }

    public Long getId() {
        return id;
    }

    public String getText() {
        return text;
    }

}

An issue-provoking scenario could be the following transaction:

引发问题的场景可能是以下交易:

import org.hibernate.Session;

public class Manager {

    public static void main(String[] args) {
        Session session = Database.getSessionFactory().getCurrentSession();

        session.beginTransaction();

        Message message = new Message("Hello, World!");
        session.save(message);

        session.getTransaction().commit();

        Database.getSessionFactory().close();
    }

}

This results in the following stack trace related to the identifier sequence:

这导致以下与标识符序列相关的堆栈跟踪:

Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:123)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:91)
    at org.hibernate.id.SequenceGenerator.generateHolder(SequenceGenerator.java:122)
    at org.hibernate.id.SequenceHiLoGenerator.generate(SequenceHiLoGenerator.java:73)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:117)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:209)
    at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:55)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:194)
    at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:49)
    at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
    at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:715)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:707)
    at org.hibernate.internal.SessionImpl.save(SessionImpl.java:702)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:356)
    at com.sun.proxy.$Proxy8.save(Unknown Source)
    at dk.radiometer.tests.hibernate.service.Manager.doTransaction(Manager.java:35)
    at dk.radiometer.tests.hibernate.service.Manager.main(Manager.java:16)
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Invalid object name 'MESSAGE_SEQ'.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1515)
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:404)
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:350)
    at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5696)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1715)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:180)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:155)
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:285)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82)
    ... 19 more

The issue seems related to the name of the sequence. My guess is that I need to manually create a sequence table of some sort for Hibernate to use, however, I do not know how to do this an have been unable to find a resource that seems related to my environment. If this is indeed the issue, please redirect me to some documentation for the protocol to follow. In addition, I am using the following programmatic Hibernate configuration:

这个问题似乎与序列的名称有关。我的猜测是我需要手动创建某种序列表供 Hibernate 使用,但是,我不知道如何执行此操作,并且无法找到似乎与我的环境相关的资源。如果这确实是问题所在,请将我重定向到要遵循的协议的一些文档。此外,我正在使用以下程序化的 Hibernate 配置:

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class Database {

    private static final SessionFactory SESSION_FACTORY = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            Configuration cfg = buildConfiguration();
            ServiceRegistry sr = new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build();
            SessionFactory sf = cfg.buildSessionFactory(sr);
            return sf;
        } catch (Throwable t) {
            System.err.println("Initial SessionFactory creation failed: " + t);
            throw new ExceptionInInitializerError(t);
        }
    }

    private static Configuration buildConfiguration() {
        return new Configuration()
            .addAnnotatedClass(Message.class)
            .setProperty("hibernate.connection.driver_class", "com.microsoft.sqlserver.jdbc.SQLServerDriver")
            .setProperty("hibernate.connection.url", "jdbc:sqlserver://SERVER_NAME;databaseName=DATABASE_NAME;integratedSecurity=true;")
            .setProperty("hibernate.connection.pool_size", "1")
            .setProperty("hibernate.dialect", "org.hibernate.dialect.SQLServer2012Dialect")
            .setProperty("hibernate.current_session_context_class", "thread")
            .setProperty("hibernate.cache.provider_class", "org.hibernate.cache.internal.NoCacheProvider")
            .setProperty("hibernate.show_sql", "true")
            .setProperty("hibernate.hbm2ddl.auto", "update");
    }

    public static SessionFactory getSessionFactory() {
        return SESSION_FACTORY;
    }

}

Thanks in advance!

提前致谢!

采纳答案by Omar Pérez

The solution to this issue is adding the catalog and schema properties to your @Table annotation.

此问题的解决方案是将目录和架构属性添加到您的 @Table 注释中。

@Table(name="<<TableName>>", catalog="<<DatabaseName>>", schema="SchemaName")

e.g

例如

@Table(name="EVENTS", catalog="EVENTMANAGER", schema="DBO")
  1. Catalog refers to the database name where the given table belongs to.
  2. Schema refers to the container (using oracle definition) to which the database belongs, in microsoft SQL Server, databases are generally created under the Database Operator (DBO) schema.
  1. 目录是指给定表所属的数据库名称。
  2. Schema是指数据库所属的容器(使用oracle定义),在Microsoft SQL Server中,数据库一般都是在Database Operator(DBO)模式下创建的。

e.g. Hibernata Mapping File (hbm) which works for me.

例如适用于我的 Hibernata 映射文件 (hbm)。

<class name="Event" table="EVENTS" catalog="EVENTMANAGER" schema="DBO">
    <id name="id" column="EVENT_ID">
        <generator class="native"/>
    </id>
    <property name="date" type="timestamp" column="EVENT_DATE"/>
    <property name="title" column="TITLE" not-null="true"/>
</class>