Hibernate 存取及批量更新删除
2007-01-30 18:35
Hibernate 存取及批量更新删除 "lian" 于:2005-08-30 02:06:54 在目标:"Hibernate 存取及批量更新删除"下添加了评论:"Hibernate 存取及批量更新删除" 文章内容: 如果你使用的底层的数据库(如Oracle)支持存储过程,也可以通过存储过程来执行批量更新。Oracle中的存储过程的设置参考如下: create or replace procedure batchUpdateCustomer(p_age in number) as begin update CUSTOMERS set AGE = AGE + 1 where AGE > p_age ; end; 上面的存储过程中的参数p_age代表一个数值型的传入参数,表示客户的年龄。我想你用它甚至可以查出一个上千年的老妖 :) 在我们的应用程序中可以对这个存储过程进行如下的调用: …….. tx = session.beginTransaction(); Connection con = session.connection(); String procedure = “ {call batchUpdateCustomer(?)}”; CallableStatement cstmt = con.prepareCall(procedure); cstmt.setInt(1, 24); cstmt.executeUpdate(); tx.commit(); 与此类同,Hibernate的批量删除也可以采用程序中调用JDBC API的方式,进行操作。你可以把上面的存储过程改一下,试着去执行它。 总结:Hibernate让我们在面对复杂多变的业务数据时,真正的体验到了面向对象编程的快意高效,但同时它自已也知道自身的不足之处在哪里,给我们留下了充分的空间去选择最适合的开发模式,而Hibernate为我们提供了对这些常规开发模式的支持。也许有一天,国人也能参与到这样经典的大型开源组件的设计当中去,做出我们引领时带的开源品牌,一同努力吧!这的确需要大部分人的努力和奉献。 相关资源: Hibernate 存取及批量更新删除 "lian" 于:2005-08-30 02:06:15 在目标:"Hibernate 存取及批量更新删除"下添加了评论:"Hibernate 存取及批量更新删除" 文章内容: 这有可能造成对一万条数据的加载和逐一删除。如此将会严重消耗内存,影响系统性能。此时最佳的方案又回到了使用JDBC API执行批量的删除工作。在此我们暂不举其实例。 下面探讨在Hibernate中的批量更新。Hibernate中Session的update()方法的各种重载形式,一次都只能更新一个对象,那么我们可不可以使用Session 的find()方法先检索出要更新的所有的对象,再用轮询的方法逐一对其进更新呢?比如: Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); Iterator customers = session.find(“from Customer c where c.age >24”) .iterator() ; while(customers.hasNext()){ Customer customer = (Customer)customers.next(); customer.setAge(customer.getAge() + 1); session.flush(); session.evict(customer); } tx.commit(); session.close(); 以上的程序只是实现了批量检索并更新对象的目的,依旧没有注意内存的占用及系统的性能问题。我们还是回到原始却又是最有效的方法,使用JDBC API来实现业务数据的批量更新。幸好Hibernate只是对JDBC进行了轻量的封装,我们在程序中依旧可以引用JDBC API: ……. tx = session.beginTransaction(); Connection con = session.connection(); //取得当前session使用的数据库连接 PreparedStatement stmt = con.prepareStatement(“update CUSTOMERS set AGE=AGE + 1 ” + “where AGE >24”); stmt.executeUpdate(); tx.commit(); 相关资源: Hibernate 存取及批量更新删除 "lian" 于:2005-08-30 02:05:00 在目标:"Hibernate 存取及批量更新删除"下添加了评论:"Hibernate 存取及批量更新删除" 文章内容: 以上的session.find( “from Customer as c”)方法,Hibernate最终会执行这样的SQL语句执行数据库的查询(立即检索方式): select * from CUSTOMERS ; 或者你也可以按如下的方式进行查询: List customerList = session.find(“from Customer as c where c.age > 24”); 最终Hibernate所执行的SQL语句为: select * from CUSTOMERS where AGE > 24 ; 如果担心一次检出Customer类对象的量会过大,可以在Customer.hbm.xml文件中设置一次批量检索的检出量batch-size: <class name=”mypack.Customer” table=”CUSTOMERS” batch-size=”4”> 对于一对一,一对多的关联也存在着集合(set. list ,bag, map)的延迟检索或立即检索,对于这种关联集合的检索,也存在着批量检索的设置,如在类的映射文件中的一对多的关联集合set中设置延迟检索时的批量检索尺寸: <class name=”mypack.customer” table=”CUSTOMERS”> …….. <set name=”topics” inverse=”true” lazy=”true” batch-size=”3”> ….. </set> </class> 对于这类检索本文不做过多解释。有兴趣的读者可参阅Hibernate的关联映射与检索类型。 关于批量删除,可以采用Session 的delete()方法的重载形式,以HQL语句作为参数执行批量的删除: session.delete(“from Customer c where c.age > 24”) ; 但是Hibernate最终并不会为我们构建这样的SQL并执行: select * from CUSTOMERS where AGE > 24 ; Session 的delete()方法首先通过以下select 语句把所有附合查询条件的Customer对象加载到内存中:select * from CUSTOMERS where AGE > 24 ; 然后再逐一执行对这些对象的删除工作: delect from CUSTOMERS where ID = 1; delect from CUSTOMERS where ID = 2; delect from CUSTOMERS where ID = 3; ……. delect from CUSTOMERS where ID = 10000; 相关资源: Hibernate 存取及批量更新删除 "lian" 于:2005-08-30 02:04:17 在目标:"Hibernate 存取及批量更新删除"下添加了评论:"Hibernate 存取及批量更新删除" 文章内容: 关于Hibernate的批量检索,批量更新和批量删除,所执行的操作并不尽遵循相同的规律。这一点使目前的Hibernate2.0还显得有些不够规格化和强健。但以后的版本中,期望其可以突破这几个屏障。 首先说明批量查询,我们已经了解到,Session 的load(), get() , find() 方法都可实现对业务数据的查询,其中load()会因所要查询的对象类的映射文件(比如Customer.hbm.xml文件)中设置的检索策略,而实现立即检索或延迟检索。get()方法和find()方法却不受这种控制,它们总是会执行立即检索。那么象load()这样的方法,当其被设置为使用延迟检索时,它会返回什么样的实例呢?当使用延迟检索时返回为这一对象的代理类实例,代理类实例也有一个标志性的OID, 但没有被实例化,其所有属性为默认初始值或为空。关于延迟检索和对象类的映射方式,这里不做多余解释。提到检索,load() 和get()方法都是用指定了OID的方式检索并返回一个与数据库中记录相对应的实例对象。如Customer customer = (Customer)session.get(Customer.class, new Long(1)) 将会返回一个Customer实例对象customer. 而 find()可以实现批量的检索,其返回类型为List的对象集合。例如: List customerList = session.find( “from Customer as c”); 注意,其中的”from Customer as c” 为HQL查询语句, Customer 并不是象普通的SQL语句中对表名的引用那样可以对大小写不敏感,这里的查询是基于对象类的,Customer为待查询的对象类,你要写正确你的类名,c是你为这个类在这里所取的别名。Hibernate是通过你对Customer这个对象类的映射文件Customer.hbm.xml中的设置得知此对象类与哪一个表对应。它可能正是对应了CUSTOMERS这个表。那么Hibernate又如何知道你所用的对象类与表的映射,到底是哪一个数据库中的表呢?这个对数据库名的映射是在Hibernate的配置文件hibernate.cfg.xml文件中给出的。相关的一些问题请查阅Hibernate的配置和映射章节。 相关资源: Hibernate 存取及批量更新删除 "lian" 于:2005-08-30 02:03:27 在目标:"Hibernate 存取及批量更新删除"下添加了评论:"Hibernate 存取及批量更新删除" 文章内容: *Session 的delete()方法 delete()方法用于从数据库中删除与Java对象对应的记录。如果传入的参数是持久化对象,Session就计划执行一个delete语句。如果传入的参数是游离对象,先使游离对象被Session关联,使它变为持久化对象,然后计划执行一个delete语句。而真正的删除语句的执行是在Session清理缓存时。示例代码如下,首先加载了一个持久化对象,然后通过delete()方法将它删除。 Session session1 = sessionFactory.openSession(); Transaction tx1 = session1.beginTransaction(); //加载一个持久化对象,因为Session 的get()和load()方法返回的永远是持久化对象。 Customer customer = (Customer)session1.get(Customer.class, new Long(1)); session1.delete(customer); session1.close(); 如果customer是游离对象时,下面的代码显示将此游离对象删除: Session session2 = sessionFactory.openSession(); Transaction tx2 = session2.beginTransaction(); //在删除前,此游离对象customer先与session2关联,成为持久对象,然后将计划 //执行对其删除的SQL语句 session2.delete(customer); tx2.commit(); session2.close(); 相关资源: Hibernate 存取及批量更新删除 "lian" 于:2005-08-30 02:02:34 在目标:"Hibernate 存取及批量更新删除"下添加了评论:"Hibernate 存取及批量更新删除" 文章内容: * Session 的load()和 get()方法 load()和 get()方法都能根据给定的OID从数据库中加载一个持久化对象,这两个方法的区别在于:当数据库中不存在与对象的OID相同的记录时,load()方法抛出net.sf.hibernate.ObjectNotFoundException异常,而get()方法返回null。示例如下: Session session1 = sessionFactory.openSession(); Transaction tx1 = session1.beginTransaction(); Customer a = (Customer)session1.load(Customer.class, new Long(1)); Customer b= (Customer)session1.get(Customer.class. new Long(2));
tx1.commit(); session1.close(); 当执行了session1.load(Customer.class, new Long(1))这样的代码以后,就把OID为1的Customer对象载到session1的缓存里。我们可以在tx1.commit()执行之前对加载后的Customer对象a进行属性的修改。这些修改并不会马上被执行,而是在Session清理缓存时,会根据持久化对象的属性变化来同步更新数据库。 相关资源: Hibernate 存取及批量更新删除 "lian" 于:2005-08-30 02:01:52 在目标:"Hibernate 存取及批量更新删除"下添加了评论:"Hibernate 存取及批量更新删除" 文章内容: 在上面的例子中,customer先是被session1持久化后,session1关闭,customer变成 游离对象,再次与session2关联后,customer又变成持久对象。其中我们不厌其烦的修改Customer对象的属性,为了要证明当Customer对象与新的session2关联以后,修改了其属性,并不需要再次执行session2.save(customer),Session在清理缓存时,会根据最近一次的更新组装成update语句并执行数据库更新。 * Session的saveOrUpdate()方法 saveOrUpdate()方法同时包含了save() 和update()方法的功能。如果传入的参数是临时对象,就调用save()方法;如果传入的是游离对象,就调用update()方法;如果传入的参数是持久化对象,就直接返回。以下的示例程序中,customer起初为游离对象, anotherCustomer起初为临时对象,session2的saveOrUpdate()方法分别将它们变为持久化对象: …… Session session2 = sessionFactory.openSession(); Transaction tx2 = session2.beginTransaction(); Customer anotherCustomer = new Customer(); // anotherCustomer为临时对象 anotherCustomer.setName(“Tom”); session2.saveOrUpdate(customer); //使customer游离对象被session2关联 session2.saveOrUpdate(anotherCustomer); //使anotherCustomer临时对象被session2关联 tx2.commit(); session2.close(); 相关资源: Hibernate 存取及批量更新删除 "lian" 于:2005-08-30 02:00:47 在目标:"Hibernate 存取及批量更新删除"下添加了评论:"Hibernate 存取及批量更新删除" 文章内容: * Session 的update()方法 update()方法使一个游离对象转变为持久化对象。以下代码在session1中保存一个 Customer 对象,然后在session2中更新这个 Customer对象: Customer customer = new Customer(); customer.setName(“Tom”); Session session1 = sessionFactory.openSession(); Transaction tx1 = session1.beginTransaction(); session1.save(customer); tx1.commit(); session1.close(); // 此时Customer对象变为游离对象,因为session1已经关闭。
Session session2 = sessionFactory.openSession(); Transaction tx2 = session2.beginTransaction(); costomer.setName(“Linda”); //在与session2关联之前修改Customer对象的属性, //这不是必须的一步,你也可以不修改,或修改更多属性。 session2.update(customer); //在session2中加载 customer游离对象,并使其再次转为 //持久化对象。 customer.setName(“Jack”); //在与session2关联之后再次修改了Customer对象的属性, tx2.commit(); session2.close(); 相关资源: Hibernate 存取及批量更新删除 "lian" 于:2005-08-30 01:59:40 在目标:"Hibernate 存取及批量更新删除"下添加了评论:"Hibernate 存取及批量更新删除" 文章内容: * Session 的save()方法: save()方法使一个临时对象转变为持久化对象。例如: Customer customer = new Customer(); customer.setId( new Long(9)); customer.setName(“Tom”); Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); Session.save(customer); tx.commit(); session.close(); Session 的save()方法所要注意的问题,1.在实际的对象持久化保存中,新建对象的ID应在此对象的类的映射文件中设置其生成方式,无需在程序中再对ID进行赋值。 例如以上的Customer类的映射文件Customer.hbm.xml中对ID生成方式的设置: <id name=”id” column=”ID”> <generator class=”increment”/> </id> 如果希望由应用程序来为新的对象指定ID,可以调用save()的另一个重载方法: save( customer, new Long(1)); 但此种方法在程序中不推荐使用。 2.在应用程序中不应该把持久化对象或游离对象传给save()方法。 相关资源: Hibernate 存取及批量更新删除 "lian" 于:2005-08-30 01:58:57 在目标:"Hibernate 存取及批量更新删除"下添加了评论:"Hibernate 存取及批量更新删除" 文章内容: 对于Hibernate所要操作的持久化对象,在它的生命周期中,可处于三种状态: ? 临时状态(transient): 用new语句新建的对象,还没有被持久化,此时它不处于任何的Hibernate 的Session之中。处于临时状态的JAVA对象被称为临时对象。 ? 持久化状态(persistent):这类对象已经被持久化,已处于(被加入)Session的缓存中。处于持久化状态的JAVA对象被称为持久华对象。 ? 游离状态(detached):已经被持久化,但不再处于Session(被扔出或是Session自行关闭了)的缓存当中。处于游离状态的JAVA对象被称为游离对象。 Session接口是Hibernate向应用程序提供的操作数据库的最主要的接口,它提供了基本的面向对象的保存,更新,删除和查询方法。它由SessionFactory工厂类创建。 |