Struts2 + Hibernate开发笔记(二)

http://35java.com/zhibo/forum.php?mod=viewthread&tid=365&extra=page%3D4

二.Action->JSP

当要从Action中执行的loadCity方法,要返回到jsp页面时,要在页面上指定一个return的页面.我们在admin-action.xml配置中可以看到一句

<resultname="city">/admin/city.jsp</result>

而在loadCity方法中有这样一句

return"city";

这样,当loadCity执行完后,就会返回到http://localhost/admin/city.jsp页面.

由于在action中,cityId和mthCity.cityId是被前一个提交过来的jsp页面赋值过,所以当程序执行转到city.jsp页面的时候,这几个值是能被使用的.我们使用jstl来获得这些值

${cityId},${mthCity.citId}(前提是只要在action中,设定了cityId和mthCity类的getter/setter.)

2.当action中的类,传到受hibernate管理的命名空间的类中时

这个问题比较特殊.

我的工程中,建立了一个类cityService.这个类是进行数据库操作的,也就是和hibernate打交道的.而这个类在hibernate的设置中设置为被一个hibernateSession管理的范围.

这个cityService中有一个方法,用于更新city的信息的

publicvoidupdateCity(MthCitycity)throwsDataAccessException,

BaseException{

MthCityicity=this.getCityById(city.getCityId());

icity.setCityName(city.getCityName());

baseHibernateDAO.update(icity);//这个baseHibernateDAO只是一个封封装了hibernateAPI的包,网上常见.

}

大家可以看到,方法中并没有直接update从参数传进来的city,而是新建了一个icity,装了city中的信息再进行update.

这是因为,cityService这个类被hibernate管理,所以在这个类中创建的内容,才能被更新.所以我们必须使用一个新的MthCity类实例来装着外面传进来的内容,才能更新.否则就会出现类似havethesameidobjectinthesession的错误,也就是说session中有其它相同id的对象的错.

当然,有另一个处理办法,就是使用baseHibernateDAO.merge来更新内容,而还是用update

这里就可以写成

publicvoidupdateCity(MthCitycity)throwsDataAccessException,

BaseException{

baseHibernateDAO.merge(icity);

}

3.Hibernate中的version类型成员

在我的项目中,city有一个属性是timestamp,对应的是mth_city这个表,这个表通过hibernate的映射,映射成一个POJO对象

publicclassMthCityimplementsjava.io.Serializable{

privateLongcityId

privateDatetimestamp;

privateStringcityName;

publicMthCity(){

}

publicLonggetCityId(){

returnthis.cityId;

}

publicvoidsetCityId(LongcityId){

this.cityId=cityId;

}

publicDategetTimestamp(){

returnthis.timestamp;

}

publicvoidsetTimestamp(Datetimestamp){

this.timestamp=timestamp;

}

publicStringgetCityName(){

returnthis.cityName;

}

publicvoidsetCityName(StringcityName){

this.cityName=cityName;

}

}

大家可以看到,类中有一个属性是timestamp,定义为Date类型.

这个类型是用于记录数据库操作的日期的,数据库中的对应字段也叫timestamp.看一下hibernate的映射配置

<?xmlversion="1.0"encoding="utf-8"?>

<!DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<!--

MappingfileautogeneratedbyMyEclipsePersistenceTools

-->

<hibernate-mapping>

<classname="com.mytophome.admin.domain.MthCity"table="MTH_CITY"dynamic-update="true">

<idname="cityId"type="java.lang.Long">

<columnname="CITY_ID"precision="10"scale="0"/>

<generatorclass="sequence"/>

</id>

<versionname="timestamp"type="java.util.Date">

<columnname="TIMESTAMP"length="7"/>

</version>

<propertyname="cityName"type="java.lang.String">

<columnname="CITY_NAME"length="80"/>

</property>

</class>

</hibernate-mapping>

大家可以看到,cityid对应数据库表中的CITY_ID字段,其值由oraclesequence生成

而timestamp属性,对应的是数据库的TIMESTAMP字段,并且这个属性在mapping中定义为<version>属性

这样,就会出现两点要注意的地方

数据库中的这个timestamp的字段一定要有值,并且是日期值,否则当hibernate更新这个字段没有值的那条记录时,会出现如下错误

org.hibernate.StaleObjectStateException:Rowwasupdatedordeletedbyanothertransaction(orunsaved-valuemappingwasincorrect):[com.mytophome.admin.domain.MthCity#1]

在更新MthCity中的值到数据库中,也就是更新一条记录时,一定不设调用方法人工设置timestamp属性的值,也就是下面的语句不能出现

mthCity.setTimeStamp(newDate());

否则也会引起hibernate的出错.

相关推荐