开发和测试业务逻辑问题集
每次在开发和测试业务逻辑biz时老是碰到这样那样似曾相识的问题,现在记一下备忘。
1、使用JPA/Hibernate/Ebean等ORM时来存取数据库时,不另外增加DAO层。理由是ORM已经封装和统一了不同数据库的基础访问、存取操作,不需要重复劳动,除非有特殊需要。
2、事务处理就是在biz层上定义的,推荐使用Spring容器来管理事务。
3、在使用事务注解时要注意@Transactional注解只能使用在public方式上才有效。放在protected/private方法上不会报错。
4、在对查询数据库操作,应使用只读事务,对数据加共享锁,以避免其他事务修改该数据。同时注意注解应使用这种形式:
@Transactional(propagation=Propagation.REQUIRED, readOnly=true)
使用Propagation.REQUIRED以确保事务的正常启动,如果使用propagation=Propagation.NOT_SUPPORTED则不会启动事务,readOnly属性实际上就失效了。
5、在使用Spring来管理Ebean的事务时,记得要设置<property name="defaultServer" value="true" />。否则死活不会成功。Ebean的Spring例子上好像有错。
6、在使用Spring来管理事务时,有两种生成代理方式。默认是Jdk自带的代理实现。推荐cglib方式,因为这种方式是使用的enhancer代理方式,是在原有XXXBizImpl上产生了一个增强的继承类,所以代理对象可以转换成XXXBizImpl。这样在测试时就更方便。因为我们业务接口方法肯定少于实现的方法。要测试实现上的各个方法,只有用cglib才能注入实现类。Jdk proxy只能注入接口。
要使用cglib除了增加相关依赖包,还要在spring中增加<aop:config proxy-target-/>。
至于两种方式的性能,可参考http://budairenqin.iteye.com/blog/1500366,如果被测的cglib版本比较低。
7、使用unitils来对biz层进行测试,并使用dbunit来初始化测试数据。使用dbunit也会有几个问题:
使用@ExpectedDataSet注解时,会出现org.dbunit.dataset.RowOutOfBoundsException: 1 > (1)异常,但不影响结果,只需要换用新版本的dbunit就行了。出错的版本是dbunit2.2.2。
(2)在配置Spring事务后,本来测试时还正常的dataset测试文件,会报出org.dbunit.dataset.NoSuchColumnException: HIP_PERSON.BASIC_ADDR_ID - (Non-uppercase input column: BASIC_ADDR_ID) in ColumnNameToIndexes cache map. Note that the map's column names are NOT case sensitive.异常。
出错的原因是第一条测试数据有8个字段,第二条测试数据只有3个,dbnit会用第一条数据的字段去要求第二条数据的,结果就报错了。结果这不是一个bug,可以看这里http://www.dbunit.org/components.html#flatxmlDataSet,
如果要想测试通过,需要把每条记录的字段都弄成一样多,但是这样太麻烦了。unitils也一直未更新解决该问题。结果只有自己重写了MultiSchemaXmlDataSetFactory。另:可自己通过DatabaseUnitils类来生成DataSet的XSD。
(3)需要注意的@ExpectedDataSet注解只验证dataset xml文件中对应的数据。不对数据库所有的数据进行验证。