题库管理模块

        题库实际是一个资料库,里面分门别类的存放着一些主题和内容。主题通常是一个问句,所以被称为题库。这个系统主要是对数据的创建,删除,修改,和查询。我主要做的是查询,修改和删除。
       在业务对象的设计上有一个有趣的问题。在我之前,业务对象已经设计好了,而且hibernate的映射文件也已经完成了。最初的设计者把这些表的所有字段,包括外键全部用property映射了。这样做就是放弃了hibernate的对象关联的功能。当我开始工作后,新的需求要求对一些关联数据进行访问,为了让其它已有的程序能够正常工作,我在hibernate映射文件里添加了many-to-one的映射,并且在类中添加了引用。已有的部分没有任何改动。代码和映射文件如下:

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Subject.java<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public   class  Subject  {
    
private String id;

    
private String baseCode;  //外键

    
private String itemCode;   //外键
    
    
private SubjectBaseCode base;   //引用
    
    
private SubjectItemCode item;     //引用
    
    
private String subDate;

    
private String aboutUser;

    
private String aboutProduct;
    
    
private Blob subjectTitle;

    
private Blob subjectContent;
    
    
private String createUser;
    
    
private Timestamp createTime;

       
//其它略
}



>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Subject.hbm.xml<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<? xml version="1.0" encoding="UTF-8" ?>

<! DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>

< hibernate-mapping
>
    
< class
        
name ="com.xxxx.model.question.Subject"
        table
="mis_tb1031_subject"
    
>

        
< id
            
name ="id"
            column
="ID"
            type
="java.lang.String"
            length
="32"
            unsaved-value
="null"
        
>
            
< generator  class ="uuid.hex" >
              
<!--   
                  To add non XDoclet generator parameters, create a file named 
                  hibernate-generator-params-Subject.xml 
                  containing the additional parameters and place it in your merge dir. 
              
-->  
            
</ generator >
        
</ id >

        
< property
            
name ="createTime"
            type
="java.sql.Timestamp"
            update
="true"
            insert
="true"
            column
="CRT_TIME"
        
/>

        
< property
            
name ="createUser"
            type
="java.lang.String"
            update
="true"
            insert
="true"
            column
="CRT_USER"
            length
="5"
        
/>

        
< property
            
name ="aboutProduct"
            type
="java.lang.String"
            update
="true"
            insert
="true"
            column
="ABOUT_PRODUCT"
            length
="500"
        
/>

        
< property
            
name ="aboutUser"
            type
="java.lang.String"
            update
="true"
            insert
="true"
            column
="ABOUT_USER"
            length
="500"
        
/>

        
< property
            
name ="baseCode"
            type
="java.lang.String"
            update
="true"
            insert
="true"
            column
="BASE_CODE"
            length
="32"
        
/>

        
< property
            
name ="itemCode"
            type
="java.lang.String"
            update
="true"
            insert
="true"
            column
="ITEM_CODE"
            length
="32"
        
/>

        
< property
            
name ="subDate"
            type
="java.lang.String"
            update
="true"
            insert
="true"
            column
="SUB_DATE"
            length
="10"
        
/>

        
< property
            
name ="subjectContent"
            type
="java.sql.Blob"
            update
="true"
            insert
="true"
            column
="SUBJECT_CONTENT"
        
/>

        
< property
            
name ="subjectTitle"
            type
="java.sql.Blob"
            update
="true"
            insert
="true"
            column
="SUBJECT_TITLE"
        
/>

        
< many-to-one
            
name ="item"
            class
="com.xxxx.model.question.SubjectItemCode"
            cascade
="none"
            outer-join
="true"
            update
="false"    
            insert
="false"
            column
="ITEM_CODE"
        
/>

        
< many-to-one
            
name ="base"
            class
="com.xxxx.model.question.SubjectBaseCode"
            cascade
="none"
            outer-join
="true"
            update
="false"
            insert
="false"
            column
="BASE_CODE"
        
/>

        
<!--
            To add non XDoclet property mappings, create a file named
                hibernate-properties-Subject.xml
            containing the additional properties and place it in your merge dir.
        
-->

    
</ class >

</ hibernate-mapping >

        由于对外键的重复映射,给以后的开发带来了一点小小的麻烦。为了保持原来程序的完整,对象之间的关联的建立,还是用原来的 baseCode, itemCode这两个String类型的属性。而关联的对象的属性 base,item仅仅在查询时有用。所以我把 base,和 item的映射属性update和insert都设为false,否则hibernate在初始化时会报错。如下:
         < many-to-one
            
name ="item"
            class
="com.xxxx.model.question.SubjectItemCode"
            cascade
="none"
            outer-join
="true"
            update
="false"     
            insert
="false"
            column
="ITEM_CODE"
        
/>

        
< many-to-one
            
name ="base"
            class
="com.xxxx.model.question.SubjectBaseCode"
            cascade
="none"
            outer-join
="true"
            update
="false"
            insert
="false"
            column
="BASE_CODE"
        
/>


       在开发的过程中,我使用了Spring的HibernateTemplate。我们的Service对象的所有方法都使用了Spring的申明式事务。
<? xml version="1.0" encoding="UTF-8" ?>
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd"
>

< beans >
    
    
< bean  id ="txProxyTemplate"  abstract ="true"
        class
="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >
        
< property  name ="transactionManager" >< ref  bean ="transactionManager" /></ property >
        
< property  name ="transactionAttributes" >
            
< props >
                
< prop  key ="save*" > PROPAGATION_REQUIRED </ prop >
                
< prop  key ="remove*" > PROPAGATION_REQUIRED </ prop >
                
< prop  key ="update*" > PROPAGATION_REQUIRED </ prop >
                
< prop  key ="delete*" > PROPAGATION_REQUIRED </ prop >
                
< prop  key ="unlock*" > PROPAGATION_REQUIRED </ prop >
                
< prop  key ="persist*" > PROPAGATION_NEVER </ prop >
                
< prop  key ="*" > PROPAGATION_REQUIRED,readOnly </ prop >
            
</ props >
        
</ property >
    
</ bean >

 
    
< bean  id ="questionService"  parent ="txProxyTemplate"   >
        
< property  name ="target" >
            
< bean  class ="com.xxxx.service.impl.QuestionServiceImpl" >
                
< property  name ="questionDao" >
                    
< ref  bean ="questionDao" />
                
</ property >
            
</ bean >
        
</ property >             
    
</ bean >     
</ beans >

       一切基本上没有什么问题。当我在做一个修改功能时问题出现了。最早完成的查询功能,查询结果用一个列表返回。后来为了使其可以删除和更新记录,所以在显示结果的表格里又新增了一列用来放删除和修改按钮。当记录被更新后,重新返回到这个列表中。所以我的action要完成两个功能,更新记录,再查询。也就是要调用2次service中的方法。一次更新,一次查询。但是问题出现了,当对象的外键属性的内容更新后,重新返回列表时,里面的内容并没有变化,但是重新查询后,结果却是正确的,而其它的字段都正常。
       于是我对程序进行跟踪,发现返回的结果中的
Subject 对象,并不是Subject类,而是hibernate的proxy类。而且里面的数据都是旧的数据。这使我白思不得其解,难道是事务没有提交。我一开始怀疑是事务的问题,可能更新的方法和查询的方法处于同一个事务中了。所以查询的时候事务还没提交,但是,我换了许多属性都不行。最后,我决定去看spring的 HibernateTemplate的源码。这是我才发现 HibernateTemplate 有一个方法
setAlwaysUseNewSession,它可以决定是不是每次execute都使用一个新的session。
       这是,我才明白,造成这个问题的原因是2个service方法都用了同一个session。再加上由于hibernate映射的问题,导致更新的时候外键更新了,但
关联对象的引用没有更新,导致 第2次查询时的关联对象是旧的。
       于是我在QuestionDaoHibernateImpl类的构造函数里
setAlwaysUseNewSession(true),但是却报错,应该是因为当 QuestionDaoHibernateImpl被spring初始化时,它的 HibernateTemplate 还没初始化。
       最后无奈,我只好用spring的initinit-method。


<? xml version="1.0" encoding="UTF-8" ?>
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd"
>
< beans >
    
<!--  Generic DAO - can be used when doing standard CRUD  -->
    
< bean  id ="baseDao"  class ="com.xxxx.dao.hibernate.BaseDaoHibernateImpl" >
        
< property  name ="sessionFactory" >
            
< ref  local ="sessionFactory"   />
        
</ property >
    
</ bean >
    
< bean  id ="questionDao"  
         class
="com.xxxx.dao.hibernate.QuestionDaoHibernateImpl"  
       parent
="baseDao"  
init-method
="setUseNewSessionTrue"   />
</ beans >

public   class  QuestionDaoHibernateImpl  extends  BaseDaoHibernateImpl  implements  QuestionDao {
    
    
/**
     * HibernateTemplate每次使用新的session.
     
*/

    
public void setUseNewSessionTrue(){
        getHibernateTemplate().setAlwaysUseNewSession(
true);
    }

    
      
//
}

      
        这样才把这个问题给解决了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值