4

我在数据加载应用程序中使用 Hibernate 3.2.5 和 Hibernate Annotations 3.3.1.GA 作为 JPA 提供程序。我已将 Hibernate 配置为使用 C3P0 进行连接池。

我的数据库是:Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production

由于 11g 没有内置的休眠方言,所以我已将其配置为使用

org.hibernate.dialect.Oracle10gDialect

JDBC驱动:Oracle JDBC驱动,版本:11.2.0.1.0

该应用程序将一些事务性能日志从大型机系统加载到 Oracle DB 中,以供以后分析和报告。它本质上是一个批处理作业,它监视一个文件夹并等待一个新文件,然后读取它并将其插入到数据库中(平均每天插入大约 450 万行),因此我选择了 Hibernate,因为它能够使用 JDBC 批处理插入经过一些比较测试后,EclipseLink 似乎效果不佳。这些文件是专有的二进制格式,因此我不能使用更简单的工具,例如 CSV 导入等。

最初我在我的工作站上开发了与 MySQL 一起使用的应用程序,因为它最初是用于一次分析任务,但现在希望将其移动到企业 Oracle RAC 平台,因为事实证明它对继续导入数据和保留数据很有用它为我自己和其他一些分析师使用了几个月。我已经让 DBA 配置了表并调整了我的实体类以反映字段名称和数据类型的一些细微变化,并更改了驱动程序和连接详细信息等,但是我遇到了一些主键生成问题。

有一些表(主数据表和一些存储各种支持类型的表,例如事务类型、用户代码等)。每个都有一个唯一的(主)id 列,该列是使用序列和更新前触发器自动生成的。

DBA 已将序列配置为他们创建的用户无法查看。

使用 JPA (javax.annotations) 生成的值类型在任何情况下都不起作用。

例如:

@GeneratedValue(strategy = GenerationType.AUTO)

这给出了 SQL:

select hibernate_sequence.nextval from dual

Oracle 驱动程序抛出异常并出现错误:

25/11/2009 11:57:23 AM org.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: 2289, SQLState: 42000
25/11/2009 11:57:23 AM org.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: ORA-02289: sequence does not exist

在发现我做了一些研究并找到了使用带有“选择”策略的 Hibernate JPA 注释扩展“GenericGenerator”的选项(http://docs.jboss.org/hibernate/stable/core/reference/en/html/ mapping.html#mapping-declaration-id-generator

例如

@GeneratedValue(generator="id_anEntity")
@GenericGenerator(name = "id_anEntity",
strategy = "select")

但是,当我使用它时,我发现 Hibernate 在 EntityManagerFactory 创建期间挂起。它似乎超越了构建属性,构建命名查询,连接到服务器,然后挂在:

25/11/2009 1:40:50 PM org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory

并且不返回。

当我没有在 persistence.xml 文件中指定方言时,我发现同样的事情发生了。

如果我使用“增量”策略,它工作得很好,尽管这意味着序列随后被破坏,因为值已经增加而序列没有增加,这不太理想。

“本机”策略提供与使用 GenerationType.AUTO 相同的输出(ORA-02289:序列不存在)。

我不确定这是因为我使用了错误的密钥生成策略,还是我的配置错误,或者是一个错误。

非常感谢使“选择”策略起作用或更好的替代方法的任何帮助。我可能会重新使用带有准备好的语句等的纯 JDBC,但这往往会有点混乱,我更喜欢 JPA 方法。

更多信息:

Persistence.xml 属性:

        <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.c3p0.min_size" value="5"/>
        <property name="hibernate.c3p0.max_size" value="20"/>
        <property name="hibernate.c3p0.timeout" value="1800"/>
        <property name="hibernate.c3p0.max_statements" value="100000"/>
        <property name="hibernate.jdbc.use_get_generated_keys" value="true"/>
        <property name="hibernate.cache.use_query_cache" value="false"/>
        <property name="hibernate.cache.use_second_level_cache" value="false"/>
        <property name="hibernate.order_inserts" value="true"/>
        <property name="hibernate.order_updates" value="true"/>
        <property name="hibernate.connection.username" value="myusername"/>
        <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver"/>
        <property name="hibernate.connection.password" value="mypassword"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
        <property name="hibernate.connection.url" value="jdbc:oracle:thin:@(DESCRIPTION =
    (ADDRESS      = (PROTOCOL = TCP) (HOST = myoracleserver) (PORT = 1521))
    (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = myservicename))
  )"/>
        <property name="hibernate.jdbc.batch_size" value = "100000" />

使用注释的实体类之一中的 ID 字段声明示例:

@Entity
@Table(name = "myentity",
catalog = "",
schema = "mydb")
public class myEntity implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @GeneratedValue(generator="id_anEntity")
    @GenericGenerator(name = "id_anEntity",
    strategy = "select")
    @Column(name = "MYENTITYID",
    nullable = false)
    private Integer myEntityID;

   //... other column mappings

    public Integer getMyEntityID() {
        return myEntityID;
    }

    public void setMyEntityID(Integer myEntityID) {
        this. myEntityID = myEntityID;
    }

   //... other getters & setters
}
4

1 回答 1

2

I'm a bit unclear on what you mean by "The DBA has configured the sequences to not be viewable by the users they have created." - does that mean that the sequence not visible to you? Why not?

In order to use sequence-based generator where sequence name is not "hibernate_sequence" (which it never is in real life; that's just the default) you need to specify the appropriate generator:

@SequenceGenerator(name="myentity_seq", sequenceName="my_sequence")
public class MyEntity {
 ...

 @Id
 @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="myentity_seq")
 private Integer myEntityID;
 ...
}

"select" generator strategy means Hibernate will try to select the row you've just inserted using a unique key (other than PK, obviously). Do you have that defined? I would strongly suggest you go with sequence instead.

于 2009-11-25T23:02:11.557 回答