问一个关于hibernate的OracleDialect问题

对于id的自动生成, OracleDialect提供了sequence的方法, 它是直接调sequence来插入ID的.
但一般做法都是用trigger来调sequence插入ID, 这种方法即安全又灵活,
不知OracleDialect怎样处理这种情况

好像没处理耶,呵呵

看看源码就清楚了~~~

原因很简单,因为session.save()一定要返回主键类对象。

你就算用trigger来读sequence生成主键字段,Hibernate还是要多调用一次SQL:select id from ...;
来获取id字段值构造主键类对象返回。

而不用trigger,也有一次SQL:select nextval from sequ来创建主键类

反正都得用两条SQL,区别也不大,你用trigger,对于Hibernate来说,反而更加麻烦,还需要用户去写trigger,索性不用。

oracle 的insert, update 有returning into clause, 不用两条sql.
trigger和returing结合是oracle的推荐方法
Insert into table_a
(value1, value2)
Select value1, value2
From table_b
Returning table_a_id
into :table_a_local;

上面的不对
Insert into table_a
(value1, value2)
Returning table_a_id
into :table_a_local;

这样做对Hibernate来说很不好,必须给每种数据库的Dialect里面加上Insert的Dialect,你觉得为了一个sequence,把Hibernate搞怎么复杂有必要吗?

再说,让Hibernate来读取sequence,或者让trigger来读取sequence,你觉得有多大差别吗?都不需要用户来管理。

再说用trigger实际上需要两条insert,一条是你在trigger里面写的insert专门用来插入主键字段,然后才是插入其它字段的insert语句。我一点都不觉得用trigger有什么好的地方,我以前用了那么多年Oracle,从来都不用trigger来插入主键。

如果你那么喜欢用trigger,你可以写自行编写一个IDGenerator来实现阿。

你难道每次只插入一条数据进表吗? 你从来不用
insert into table_1 (value_1, value_2)
select value_1, value_2 from table2 吗?
这种情况下你怎么单用sequence创建主键


JDO就支持trigger创建主键
http://castor.exolab.org/key-generator.html

trigger创建主键也没有什么特别的阿,你觉得Hibernate没有自己写一个也好阿,反正我觉得没什么用。

你说的这个sql语句,Hibernate无法生成这样的sql,所以也根本就用不上trigger创建主键。使用trigger实际上是进行了两次insert,有什么好的,不明白。

我们创建数据库不是只为hibernate用的, 用trigger不光可解决批量插入的问题, 而且他还可解决sequence的并发问题. 基本上好的数据库设计都采用这个方法, 只是你不知道而已
我已经发了mail给Gavin King, 以后版本就会支持了.

那你还不如自己把代码写出来提交给Gavin呢,这样我们也可以在Hibernate里面看到中国人贡献的代码了,不是更好吗?写个Generator也不麻烦阿。

你一个表用一个sequence,怎么会有并发问题?除非你所有的表都用一个sequence。再说你觉得用trigger为了插入一条数据要发送两条insert,这样效率不会很低吗?数据库的负担也会加重的。

insert into table_1 (value_1, value_2)
select value_1, value_2 from table2 吗?

这样的sql语句,你索性把主键字段一并复制过去不就得了,何必另外生成主键那么麻烦呢?

在Hibernate里面的1:1关系就是这样处理的,一方采用主键生成技术产生主键,另一方直接把对方的主键拿过来用。

trigger 是这样写的, 不是另一条insert, ,

create trigger y before insert on bob
for each row
when (new.a is null)
begin
select x.nextval into :new.a from dual;
end;

当我们插入单条或批量数据时, 不用考虑主键, trigger 会自动加上的.
而且trigger 是单步执行, 不会出现并发访问sequence的情况. 可减少数据库的contention, 而且我们在做表移植等维护操作时可暂时disable trigger, 还有我们可加一些条件在trigger 里, 可对主键强行付值.
总之, 好处多多.

我对hibernate只是使用, 并不打算深研究, 修改就谈不上了

/*insert into table_1 (value_1, value_2)
select value_1, value_2 from table2 吗?

这样的sql语句,你索性把主键字段一并复制过去不就得了,何必另外生成主键那么麻烦呢?*/

这可以是批量插入, 也不光是复制全表, 复制主键有时会冲突的

eg.
insert into table_1 (value_1, value_2)
select value_3, value_4 from table2
where a>50

这里还有一个潜在问题,如果我的程序象多兼容几个数据库,而且编号还是有一点意义,只能使用native,这时候,hibernate只会创建一个sequence,而不能为每个表建一个。另一种选择就是做两个配置文件,这是我们所不喜欢的。
所以我觉得最好能默认为所有表建单独的sequence比较合适。

看看我这个SQL:

insert into table_1 (id, value_1, value_2)
select mysequence.nextval, value_3, value_4 from table2
where a>50

mysequence是一个序列,看到了吗?批量插入,也用不着trigger来帮忙读取序列吧!总的来说trigger实现了类似SQL Server的autoincrement字段的作用,如果写JDBC的话,用不着用户来管理,会方便一些,但把序列和字段分开来更灵活,总之我不觉得这样用有什么特殊的好处。

这个功能对Hibernate来说可有可无,但是如果要在Hibernate加上这个功能却很麻烦,因为Hibernate还不支持"insert ... returning ..."的语法,我粗粗的想了想,至少有6个类的源代码要修改,我不太相信Gavin 会为了一个可有可无的功能而大动干戈。