java中Hibernate使用Oracle数据库遇到的几个问题
Hibernate作为一个成熟的持久层解决方案,通过简单的配置,可以在不修改源码的情况下,无缝的在不同的数据库上运行。尽管如此,使用不同的数据库仍然会出现一些问题,比如本文要讨论的Oracle中的问题。
1. Hibernate无法创建hibernate_sequence的问题
错误提示:
问题分析:
从错误提示上看,查询语句没有找到hibernate_sequence这个序列。到Oracle数据库中查看,果然没有。按道理说,hibernate应该在Oracle中自动生成这个序列,那为什么没有生成呢?原因主要有两个:
1.hibernate的核心配置中没有设置自动建对象的属性,导致无法自动建立序列:
<property name="hibernate.hbm2ddl.auto">update</property>
2.其他用户存在hibernate_sequence这个序列,导致当前用户不再创建该序列。
原因:
hibernate在启动时即需要去检测所要创建的序列是否存在,如果存在,则不再创建此序列。在某些情况下,hibernate能够探测到其它用户所创建的同名序列,而被认为不再需要创建序列,这时候如果进行保存数据的操作,就会因为在当前用户下找不到该序列从而导致出错。
要解决这个问题的首要方法是需要找到hibernate判断指定序列是否存在的方法,在hibernate的dialet中,取决于getQuerySequencesString这个方法,此方法返回了查询所有序列的方法。
Hibernate中的与Oracle相关dialet一般配置为Oracle10gDialect、Oracle9iDialect、Oracle8iDialect。从源码我们可以看到他们之间是继承关系,如:Oracle10gDialect extend Oracle9iDialect extend Oracle8iDialect extend Dialet。通过源代码我们可以看出,该方法只是在Oracle8iDialect中进行了覆写,其子类都沿用了该实现。实现代码如下:
public String getQuerySequencesString() {
return " select sequence_name from all_sequences"
+ " union"
+ " select synonym_name"
+ " from all_synonyms us, all_sequences asq"
+ " where asq.sequence_name = us.table_name"
+ " and asq.sequence_owner = us.table_owner";
}
从代码分析看,它是从all_sequence中寻找所能找到的sequence,而当前用户能找到的sequence全在于当前用户能有多大的权限,以及具体的oracle jdbc实现。在这种情况下,如果当前用户拥有dba权限(开发时候,经常给一个用户授dba权限)或者由于其它某种原因,就能够找到其他用户的sequence了。而如果其他用户也创建了一个叫hibernate_sequence的sequence,那hibernate在当前用户就不能再创建sequence了。
知道了这个原因后,如何解决呢?
我们可以创建一个新的OracleDialect,直接继承于Oracle10gDialect,并在新的类中覆盖getQuerySequencesString方法,将其中的sql语句改为从user_sequences(即当前用户的sequence空间)中寻找相应的序列,这样就不会寻找到其它用户的序列了。参考代码如下:
public class Oracle10gDialectEx extends Oracle10gDialect {
public String getQuerySequencesString() {
return "select sequence_name from user_sequences";
}
}
还有个解决办法,就是去掉该Oracle用户的跨用户访问的权限,如select any table的权限或dba角色。
2. 使用hibernate生成表不能正确创建表的问题
问题:
hbm2ddl.auto配置成update时,发现hibernate并没有按照默认的生成规则生成相应的数据表信息
分析发现,这里需要引用的表p_menu在另一个用户空间里已经存在了,而hibernate在创建表时,在另一个用户空间中找到了这个表,故不再在当前的用户空间中创建这个表了。而在创建关联表时,由于关联的是本用户空间的表,故有此错误。
hibernate使用了jdbc默认的databasemeta来寻找相应表数据信息,当使用默认的配置时,由于某种原因(并不是每次都能发生,取决于数据库本身以及相应的驱动)。当使用当前用户连接到数据库时,使用databasemeta寻找数据库表信息时,会查询出其它用户的数据表信息(即使当前用户没有相应的权限)。
两种解决方案:
1.在hibernate核心配置中配置一个属性:
<property name="hibernate.default_schema">当前连接用户</property>
2.在hbm文件配置中的class元素中指定schema=""的属性
<class name="class" table="table" schema="当前连接用户">
3.去掉该Oracle用户的跨用户访问的权限,如select any table的权限
3. SSH启动中的输出日志中有createClob的info信息的问题
在使用SSH+Oracle启动的时候,控制台会打印:
INFO: HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException
如果是使用的Oracle10G,实体类使用了Clob字段的时候,会抛出这个信息。
如果使用的是Oracle11G,实体类使用了复杂的数据类型的时候,也会抛出这个信息。
分析:
这个东西只是个 INFO 级别的,也就是说仅仅是提醒,无关紧要的。但总觉的不爽。如何解决呢?
从驱动上寻找解决方案:
使用Oracle10G,将默认的JDBC驱动ojdbc14升级为更高版本,如Oracle11G的ojdbc6.jar的版本。
从hibernate上寻找解决方案:
修改hibernate配置项hibernate.temp.use_jdbc_metadata_defaults=false。
另外:Hibernate4的官方资料里说11g和10g都是Oracle10gDialect,方言通用,这个没啥影响。
版权声明:部分文字转载来自公开网络,版权归作者本人所有,推送文章除非无法确认,我们都会注明作者和来源。如果出处有误或侵犯到原作者权益,请与我们联系删除或授权事宜。
【免责声明】本文部分系转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,如涉及作品内容、版权和其它问题,请在30日内与我们联系,我们会予以重改或删除相关文章,以保证您的权益!
Java开发高端课程免费试学
大咖讲师+项目实战全面提升你的职场竞争力
- 海量实战教程
- 1V1答疑解惑
- 行业动态分析
- 大神学习路径图
相关推荐
更多2024-04-08
2024-04-02
达内就业喜报
更多>Java开班时间
-
北京 丨 11月27日
火速抢座 -
上海 丨 11月27日
火速抢座 -
广州 丨 11月27日
火速抢座 -
兰州 丨 11月27日
火速抢座 -
杭州 丨 11月27日
火速抢座 -
南京 丨 11月27日
火速抢座 -
沈阳 丨 11月27日
火速抢座 -
大连 丨 11月27日
火速抢座 -
长春 丨 11月27日
火速抢座 -
哈尔滨 丨 11月27日
火速抢座 -
济南 丨 11月27日
火速抢座 -
青岛 丨 11月27日
火速抢座 -
烟台 丨 11月27日
火速抢座 -
西安 丨 11月27日
火速抢座 -
天津 丨 11月27日
火速抢座 -
石家庄 丨 11月27日
火速抢座 -
保定 丨 11月27日
火速抢座 -
郑州 丨 11月27日
火速抢座 -
合肥 丨 11月27日
火速抢座 -
太原 丨 11月27日
火速抢座 -
苏州 丨 11月27日
火速抢座 -
武汉 丨 11月27日
火速抢座 -
成都 丨 11月27日
火速抢座 -
重庆 丨 11月27日
火速抢座 -
厦门 丨 11月27日
火速抢座 -
福州 丨 11月27日
火速抢座 -
珠海 丨 11月27日
火速抢座 -
南宁 丨 11月27日
火速抢座 -
东莞 丨 11月27日
火速抢座 -
贵阳 丨 11月27日
火速抢座 -
昆明 丨 11月27日
火速抢座 -
洛阳 丨 11月27日
火速抢座 -
临沂 丨 11月27日
火速抢座 -
潍坊 丨 11月27日
火速抢座 -
运城 丨 11月27日
火速抢座 -
呼和浩特丨11月27日
火速抢座 -
长沙 丨 11月27日
火速抢座 -
南昌 丨 11月27日
火速抢座 -
宁波 丨 11月27日
火速抢座 -
深圳 丨 11月27日
火速抢座 -
大庆 丨 11月27日
火速抢座