hibernate真不是给普通人用的......
为什么要用hibernate,因为写sql语句太麻烦了。为什么要用hibernate,因为我对sql语句不是很熟悉。简单的说,用hibernate的一般都是初学者。可是,hibernate的各种举动远远超乎我这种初学者的想象。
1)奇观一:写入和查询语句不执行。
写了个简单的session.save(obj)语句,你却发现它并不执行。原来是因为数据库表是事务表,所以,需要把这个语句放到事务里面执行。这个还好说。
过了不久,你发现query查询居然没有执行!你把hibernate生成的sql语句放到数据库客户端执行,明明有好些结果,可是,hibernate愣是不给你出结果!它也不是老不出,一段时间之后,它就执行了,会给你一个结果。查询语句居然不是实时的...... 在google了很长时间之后(半天),才看到一个说法:把查询语句用事务封装起来。于是这么做了,于是就发现hibernate能够马上执行查询语句了。
2)奇观二:执行本地SQL语句返回结果奇特。
数据库中有几个表,需要进行左连接访问(left join),用sql语句很容易做到。可是,当你打算用hql语句来做到这点的时候,你就蒙了。你发现配置那个麻烦啊,没有直接写sql语句简单。所以,你就直接写sql语句了,期待着hibernate能够像普通的jdbc那样,返回一个正确的结果。然而,看到返回的结果,你傻眼了。为什么?
数据库表里面有一个字段类型char(4),里面的值都是“good”,可是,hibernate查询回来的居然只有一个字符:“g”。只好查看hibernate的ref里面的Native Sql那章了,看到有如下的例子:
sess.createSQLQuery("SELECT * FROM CATS")
.addScalar("ID", Hibernate.LONG)
.addScalar("NAME", Hibernate.STRING)
.addScalar("BIRTHDATE", Hibernate.DATE)
你才知道,你需要使用addScalar方法来指定某个返回字段的类型!注意的是,方法里面的第一个参数是返回字段的名称。哦,你恍然大悟。立马这样修改了自己的代码,慢着,你突然发现居然只返回了你使用addScalar指定了类型的几个字段!原来,hibernate就是这样处理的,你要返回的每个字段都必须使用addScalar指定!
3)奇观三:无法简单执行基本函数。
很多时候,我们都有一个需求:得到数据库服务器的当前时间。这是因为本机时间和服务器时间是有差别的。各种数据库都提供了函数来获得,比如,mysql,可以用“select now()”。hibernate也提供了一个函数current_timestamp(说起timestamp,个人认为数据库的timestamp做的很差,它居然和datetime是一个数量级的(精确度),这怎么可以用来表示真正的stamp啊!)。可是,你却无法用直接使用“select current_timestamp()”来获得服务器的当前时间,你还必须加上一个查询的表!比如,“select current_timestamp() from tbl_Good”。个人十分郁闷,我只是想用这个简单功能而已,为什么我一定要知道数据库里面的表格呢????更何况还必须建立映射。。。。。。
不是我不明白,这世界太复杂了 。每样产品都是拼命的复杂化,其实,它们实在是忽略了一般的用户只需要一小部分功能而已。默认的功能应该是能够满足普通用户的常见需求的,那样才算是一个好的产品。我不认为hibernate做到了这点。
4) 奇观四:写入数据库字符串乱码。
简单的数据库,简单的表格,简单的字段,是字符串类型,utf-8编码。用hibernate写入正常文本,写进去就变成乱码了。显然是编码不一致的问题。hibernate里面居然没有说明如何配置。好在网络上有人说可以在hibernate的配置文件里面加上一句配置:
<property name="connection.characterEncoding">UTF-8</property>
这句配置并不是给hibernate用的,它会传递给底层的jdbc。告诉jdbc字符串是utf-8的编码。可能有的数据库会需要你再配置一个(以上配置mysql可以):
<property name="connection.useUnicode">true</property>