项目中使用了ssh作为开发底层框架,由于在开发前期并没有限制项目运行在哪一个数据库之上,因此在hibernate的配置上使用Generated的id生成方式,使得能够在不修改源代码的情况下,无缝的在不同的数据库上跑,只需要修改配置文件中的dialect即可。
在这种情况下,在oracle中,hibernate就会使用一个叫做hibernate_sequence的全局sequence来作为所有主键的生成sequence,在新增一条记录之上,均需要从此sequence中取一个数值,并作为其他记录的主键插入到数据库当中。
然后,这个hibernate_sequence并不是在项目启动之前手动地创建的,而是使用了hiberante的create-update方式,即创建-修改的方式进行创建。既然是这样,那么hibernate在启动之前即需要去检测所要创建的sequence是否存在,如果存在,则不再创建此sequence。然而,在某些情况下,hibernate能够探测到其它用户所创建的sequence,而被认为不再需要创建sequence,这时候就会在项目运行中出错了。出错的原因,即找不到相应的sequence。
这个错误和hibernate不会主动创建某些表一致,不一样的是hibernate用的是另一个判断语句来判断相应的sequence是否存在。
相关链接:解决在oracle数据库中使用hibernate生成表不能正确创建表的问题.
解决这个问题的首要方法是需要找到hibernate判断指定sequence是否存在的方法,在hibernate的dialet中,取决于getQuerySequencesString这个方法。此方法返回了查询所有sequence的方法。而在Oracle8iDialect,Oracle9iDialect,Oracle10gDialect中,此方法的实现如下:
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了。
相比如,前面3个oracle dialect实现,在Oralce9Dialect,OracleDialect(这两个dialect不被建议使用)中,此方法的实现如下:
public String getQuerySequencesString() { return "select sequence_name from user_sequences"; }
初看这个实现,其实已经是我们在一般开发过程中所需要的东西了,即从user_sequences(即当前用户的sequence空间)中寻找相应的sequence,这样就不会寻找到其它用户的sequence了。
找到了两个不同的实现,那么最后的解决方法就很简单了。我们需要创建一个新的OracleDialect,并且为了使用没有被废弃的类,即需要继承于Oracle10gDialect,并且ovveride getQuerySequencesString方法,实现的方法,即是从当前user_sequences中寻找sequence了。完整的实现即如下所示:
public class Oracle10gDialectEx extends Oracle10gDialect { public String getQuerySequencesString() { return "select sequence_name from user_sequences"; } }
上面的代码,仅为解决hibernate不能正确的创建sequence,由于在Oracle8iDialect的实现当中,还使用了synonyms,因此对于某些特殊的Oracle项目,还是仔细权衡是否能这样做。不过由于笔者所涉及到的项目,并没有使用到这么高级的oracle特性,因此,修改完全有效。
转载请标明出处:i flym
本文地址:https://www.iflym.com/index.php/code/resolve-oracle-use-hibernate-can-not-create-hibernate-sequence-during-some-conditions.html
补充另外一个问题,可能是由于oralce权限造成的:如下所示
http://www.iflym.com/index.php/code/minimize-user-privs-to-avoid-error-data-in-hibernate-development.html
给当前项目的用户,分配了过多的数据库权限。