- 当我们调用 Hibernate 的 saveOrUpdate() 或 JPA 的 save() 方法的 Hibernate 实现时,都会做两步操作:1)按 ID 查询记录是否已存在,2)不存在插入新记录,存在则更新原记录。这种两步操作其实可以在 SQL Server 和 HSQLDB 中一条语句完成,这就是本文要介绍的
merge into语句。感觉到用数据库自己的特性,并且一条语句会比saveOrUpdate()两步操作性能要好,还需实测。
之所以把 SQL Server 和 HSQLDB 扯到一块来讲,是因为我们在实际项目中的单元测试是基于 HSQLDB 内存数据库的。merge into如其名所示,它应该是给予我们便利的去根据把一个表中符合条件的记录合并到另一个表中去。我们这里只利用它的这特性去实现类似 Hibernate 的saveOrUpdate()操作。
假设我们有一个简单的表1CREATE TABLE user ( 2 id INT, 3 name VARCHAR(32), 4 address VARCHAR(128) 5);
如果指 id 的记录已存在更新原来记录的 name 和 address, 不存在则插入新记录 Read More - Hibernate 3 之后,formula(公式,Excel 里常见的) 得到了更广泛的应用,不过这里还是简单记录一下它在 <property> 中的应用。
假如我们要映射这么一个类:
package cc.unmi.model;
public class User {
private int id;
private String name;
Private Set<Order> orders = new HashSet<Order>();
//setter & getter ......
} Read More - 我们在使用 Hibernate 时一般只会关注是否显示生成的 SQL 语句,不过有些时候还不够。默认时 Hibernate 执行的 SQL 语句是打印在控制台上的,它也可以配置为输出给 Log4J 或是 Log4Back,还能显示出更详细的参数和取值信息。这里简单讲来。
Hibernate 的配置文件 hibernate.cfg.xml 里提供有三个有关显示 SQL 的配置项,如果是与 Spring 联合,也可以配置到 Spring 的配置中。它们的取值是 boolean 值。
1) hibernate.show_sql - 是否显示所生成 SQL 语句,我们最常和它打交道
2) hibernate.format_sql - 是否格式化生成的 SQL 语句,增加可读性,不然全挤在一行
3) hibernate.use_sql_comments - 是否显示注释,用以指出什么操作产生的 SQL 语句,相比上面两条而言,这个配置会稍稍陌生些
来看看加了上面三条配置后产生的效果,执行了 Hibernate 查询后,在控制台上产生如下输出: Read More - 在使用 Hibernate 进行数据库操作的时候可以显示出所执行的 SQL 语句,相信用 Hibernate 的兄弟姐妹们都知道怎么设置。就设置 hibernate.show_sql 或者 show_sql 属性为 true 就行,在 hibernate.cfg.xml 或者与 Spring 集成时配置在 Spring 的配置文件中。再就是要让显示的 SQL 语句是格式化的,就配置 hibernate.format_sql 或是 format_sql 为 true,否则总在一行中执行。Hibernate 显示的 SQL 语句好像是通过 System.out.println() 直接输出的。
Hibernate 大部份时候是通过 PreparedStatement 来执行 SQL 语句的,它的好处是可预处理、被缓存,可防止注入。只是这样让 Hibernate 执行的 SQL 语句输出到控制台是带问号的,如: Read More - 做 Java Web 应用我想多会采用这两种框架组合,SSH 和 SSI,其实我是不太喜欢用这两种缩写方式:
SSH = Spring + Struts + Hibernate,SSH 由久已久所代表的是 Secure Shell,像 https
SSI = Spring + Struts + iBatis,SSI 在很久以前就是 Server Side Include,像 shtml,而 iBatis 已更名为 MyBatis 了。
要是在以往做这样的 Java 项目都会用 Commons-Logging + Log4J 来作为日志框架,因为多数组件用的是 Common-Logging 通用组件,而那时 Log4J 控制实际的日志输出也是最强的。
Read More
直接以一个例子在说明,如DB2中有一个简单存储过程 selectAllUsers1CREATE procedure selectAllUsers 2DYNAMIC RESULT SETS 1 3BEGIN 4 DECLARE temp_cursor1 CURSOR WITH RETURN TO CLIENT FOR 5 SELECT * FROM test; 6 OPEN temp_cursor1; 7END;
映射文件中关于存储过程内容如下 Read More- 在过去使用 Spring 整合 Hibernate 的时候,都是用这样的配置方式。
1<bean id ="sessionFactory" lazy-init ="true" 2 class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 3 <property name ="mappingResources"> 4 <list> 5 <value>resources/icustomer/Contact.hbm.xml</value> 6 <value>resources/icustomer/Customer.hbm.xml</value> 7 </list> 8 </property> 9 ................... 10</bean>
Read More
Hibernate save 在 session 中已存在相同 OID(主键) 的对象,会出现异常,详细内容如下:
Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.unmi.LoanDetail#1]
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:168)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient Read More
用Hibernate也有一段时间了,项目中也用过CMP以及.net的DataSet,也想体验一下iBatis的SqlMap方式的魅力了,以前总是看iBatis介绍一的文章,现在应是亲自动手心临其境的时候了。
做这个实验基本是遵照 iBATIS SQL Maps 入门教程 中的例子做的,只是在原来的基础上还更简化了一些。
我用的开发工具是 Eclipse,如何建立你的工程和加入相应的 iBatis 包可不详叙。 Read More
Hibernate应用程序部署到WebSphere Application Server 5.1上,使用WAS的连接池,程序在处理了比较多的 session.save(object)操作之后,在执行提交事物 trans.commit()之时出现以下异常
java.lang.NullPointerException
at oracle.jdbc.dbaccess.DBData.clearItem(DBData.java:431)
at oracle.jdbc.dbaccess.DBDataSetImpl.clearItem(DBDataSetImpl.java:3528)
at oracle.jdbc.driver.OraclePreparedStatement.clearParameters(OraclePreparedStatement.java:3401)
at com.ibm.ws.rsadapter.jdbc.WSJdbcConnection.resetStatement(WSJdbcConnection.java:1719) Read More