首页 文章

Hibernate与Oracle 11g无法使用“select”生成器

提问于
浏览
4

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

我的数据库是:Oracle Database 11g企业版11.1.0.7.0版 - 64位 生产环境

因为11g没有内置的hibernate方言,所以我已将其配置为使用

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"和"select"策略的选项(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")

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

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

并且不会回来 .

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

如果我使用“增量”策略,它工作正常,虽然这意味着序列随后被递减,因为值已经递增而序列没有增加,这是不太理想的 .

“native”策略提供与使用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
}

1 回答

  • 2

    我对你的意思有点不清楚“DBA已经将序列配置为不能被他们创建的用户查看 . ” - 这是否意味着您不可见的序列?为什么不?

    为了使用基于序列的生成器,其中序列名称不是"hibernate_sequence"(它从未在现实生活中;这只是默认值),您需要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"生成器策略意味着Hibernate会尝试使用唯一键(显然除了PK之外)选择刚刚插入的行 . 你有定义吗?我会 strongly 建议你改顺序 .

相关问题