使用Spring对Service层进行测试,无法查询到刚刚插入的记录?

问题描述

如题,本人使用Spring提供的:AbstractTransactionalDataSourceSpringContextTests类对Service层进行测试。测试的方法是向数据库中插入一条用户记录,然后再重新检索出来。代码如下:【1】DAO层代码:public User saveUser(User newUser) {getHibernateTemplate().save(newUser);//getHibernateTemplate().flush();return (User) getHibernateTemplate().get(User.class,newUser.getUserId());}【2】Service层代码:public User saveUser(User newUser) throws NewsletterException {try {return userDao.saveUser(newUser);} catch (HibernateObjectRetrievalFailureException he) {throw new ServiceException(systemMessage.getMessage(SERVICE_FAILED)+ ": saveUser");} catch (Exception e) {throw new NewsletterException(e.getMessage());}}public User getUserByName(String userName) throws NewsletterException {try {return userDao.getUserByName(userName);} catch (HibernateObjectRetrievalFailureException he) {throw new ServiceException(systemMessage.getMessage(SERVICE_FAILED)+ ": userName");} catch (Exception e) {throw new NewsletterException(e.getMessage());}}【3】测试代码:public void testSaveUser() {User newUser = createUser();try {userService.saveUser(newUser);assertTrue(true);String sql = "Select USERNAME from NEWSLETTER_USER where UPPER(USERNAME)= ?";String userName = (String) jdbcTemplate.queryForObject(sql,new Object[] { "PAUL" }, java.lang.String.class);assertNotNull(userName);assertEquals(userName, newUser.getUserName());} catch (NewsletterException ne) {fail(ne.getMessage());}}【4】Spring配置文件:<!-- User Service Definition --><bean id="userServiceTarget"class="com.newsletter.service.impl.UserServiceImpl"><property name="userDao"><ref local="userDao" /></property><property name="systemMessage"><ref local="systemMessage" /></property></bean><!-- Transactional proxy for the User Service --><bean id="userService"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><property name="transactionManager"><ref local="transactionManager" /></property><property name="target"><ref local="userServiceTarget" /></property><property name="transactionAttributes"><props><prop key="get*">PROPAGATION_REQUIRED,readOnly</prop><prop key="save*">PROPAGATION_REQUIRED</prop><prop key="update*">PROPAGATION_REQUIRED</prop><prop key="delete*">PROPAGATION_REQUIRED</prop></props></property></bean>【5】测试问题:1. 使用上面的测试代码,发现jdbcTemplate.queryForObject方法获取到的结果为空,测试失败。2. 在testSaveUser方法末尾,即便加上setComplete()方法,发现数据已经插入,但query方法同样返回NULL3. 假如我使用上面Service层的userService.getUserByName方法进行测试,测试通过4. 假如我在DAO层的saveUser方法里面加上getHibernateTemplate().flush();测试也通过请问为什么即便我在测试方法中加上setComplete(),而且数据库中查到了记录,但每次都是返回NULL是什么原因?问题补充:谢谢llade,假如我调用了setComplete()方法,Spring确实是提交了事务的,因为我在数据库中已经查询到相应的记录。我测试过3种情况的setComplete(),第一种是在saveUser调用之后,第二种是在queryForObject之后,第三种是分别在saveUser和queryForObject之后。但每次都是同样的结果。

解决方案

需要将hibernate的session,flush一下SessionFactoryUtils.getSession(getSessionFactory(), false).flush()这样你刚才做的操作才会体现在实际的数据库表中。然后通过jdbc就能查到了。public void testSaveUser() { User newUser = createUser(); try { userService.saveUser(newUser); [b]SessionFactoryUtils.getSession(getSessionFactory(), false).flush();[/b] assertTrue(true); String sql = "Select USERNAME from NEWSLETTER_USER where UPPER(USERNAME)= ?"; String userName = (String) jdbcTemplate.queryForObject(sql, new Object[] { "PAUL" }, java.lang.String.class); assertNotNull(userName); assertEquals(userName, newUser.getUserName()); } catch (NewsletterException ne) { fail(ne.getMessage()); }}
解决方案二:
那是因为, Hibernate和JDBC不在一个事务内.所以, [1] 你把Hibernate的Session Flush后, JDBC就可以查到了.[2] 你不用JDBC去查,继续使用Hibernate去查询,当然还可以查到.最近一直在看Hibernate和JDBC的框架整合,就一直遇到同类的问题.
解决方案三:
有意思的问题。在这种情况下还是先看看到底Connection有没有commit吧。方法是,做一个代理类,看看connecton有没提交。package llade.test.jdbcimport java.sql.CallableStatement;import java.sql.Connection;import java.sql.DatabaseMetaData;import java.sql.PreparedStatement;import java.sql.SQLException;import java.sql.SQLWarning;import java.sql.Savepoint;import java.sql.Statement;import java.util.Map;import org.apache.commons.dbcp.BasicDataSource;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;public class MyDataSource extends BasicDataSource {Log logger = LogFactory.getLog(MyDataSource.class);class ProxyConnection implements Connection{Connection innnerConnection;String uuid;public ProxyConnection(Connection conn,String uuid){this.innnerConnection=conn;this.uuid=uuid;}public void clearWarnings() throws SQLException {this.innnerConnection.clearWarnings();}public void close() throws SQLException {this.innnerConnection.close();}public void commit() throws SQLException {//正是我们想要知道是否调用了commit(); //如果信不过logger可以用System.outlogger.debug("connection:"+this.uuid+" commit");this.innnerConnection.commit();}public Statement createStatement() throws SQLException {return this.innnerConnection.createStatement();}public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {return this.innnerConnection.createStatement(resultSetType, resultSetConcurrency);}public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return this.innnerConnection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);}public boolean getAutoCommit() throws SQLException {return this.innnerConnection.getAutoCommit();}public String getCatalog() throws SQLException {return this.innnerConnection.getCatalog();}public int getHoldability() throws SQLException {return this.innnerConnection.getHoldability();}public DatabaseMetaData getMetaData() throws SQLException {return this.innnerConnection.getMetaData();}public int getTransactionIsolation() throws SQLException {return this.innnerConnection.getTransactionIsolation();}public Map<String, Class<?>> getTypeMap() throws SQLException {return this.innnerConnection.getTypeMap();}public SQLWarning getWarnings() throws SQLException {return this.innnerConnection.getWarnings();}public boolean isClosed() throws SQLException {return this.innnerConnection.isClosed();}public boolean isReadOnly() throws SQLException {return this.innnerConnection.isReadOnly();}public String nativeSQL(String sql) throws SQLException {return this.innnerConnection.nativeSQL(sql);}public CallableStatement prepareCall(String sql) throws SQLException {return this.innnerConnection.prepareCall(sql);}public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {return this.innnerConnection.prepareCall(sql, resultSetType, resultSetConcurrency);}public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return this.innnerConnection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);}public PreparedStatement prepareStatement(String sql) throws SQLException {return this.innnerConnection.prepareStatement(sql);}public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {return this.innnerConnection.prepareStatement(sql, autoGeneratedKeys);}public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {return this.innnerConnection.prepareStatement(sql, columnIndexes);}public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {return this.innnerConnection.prepareStatement(sql, columnNames);}public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {return this.innnerConnection.prepareStatement(sql, resultSetType, resultSetConcurrency);}public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return this.innnerConnection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);}public void releaseSavepoint(Savepoint savepoint) throws SQLException {this.innnerConnection.releaseSavepoint(savepoint);}public void rollback() throws SQLException {this.innnerConnection.rollback();}public void rollback(Savepoint savepoint) throws SQLException {this.innnerConnection.rollback(savepoint);}public void setAutoCommit(boolean autoCommit) throws SQLException {this.innnerConnection.setAutoCommit(autoCommit);}public void setCatalog(String catalog) throws SQLException {this.innnerConnection.setCatalog(catalog);}public void setHoldability(int holdability) throws SQLException {this.innnerConnection.setHoldability(holdability);}public void setReadOnly(boolean readOnly) throws SQLException {this.innnerConnection.setReadOnly(readOnly);}public Savepoint setSavepoint() throws SQLException {return this.innnerConnection.setSavepoint();}public Savepoint setSavepoint(String name) throws SQLException {return this.innnerConnection.setSavepoint(name);}public void setTransactionIsolation(int level) throws SQLException {this.innnerConnection.setTransactionIsolation(level);}public void setTypeMap(Map<String, Class<?>> map) throws SQLException {this.innnerConnection.setTypeMap(map);}}@Overridepublic Connection getConnection() throws SQLException {Connection conn=super.getConnection(); return new ProxyConnection(conn,java.util.UUID.randomUUID().toString());}@Overridepublic Connection getConnection(String user, String password) throws SQLException {Connection conn=super.getConnection(user,password);if(conn instanceof ProxyConnection)return conn;return new ProxyConnection(conn,java.util.UUID.randomUUID().toString());}}

时间: 2024-12-29 14:22:18

使用Spring对Service层进行测试,无法查询到刚刚插入的记录?的相关文章

spring hibernate service层执行hql问题

问题描述 在service层中写hql,然后直接使用dao调用,返回值是Object类型,里面的参数名字也变成了01234...而在service层调用dao,dao执行hql,则不会出现这种问题,会返回正常实体跑断点发现返回值类型是由一个queryPlanCache的东西管理的然后这个东西是在SessionFactoryImplementor中,而跑断点没看到这个对象中的返回值类型是什么时候设定的,在执行的时候就已经存在了,求大神解释为何service层中写hql,并使用baseDao执行hq

如何使用spring将service层注入到servlet中去(how to use Spring to inject ur service layer into the servlet )

In a typical struts+spring framework, we know how to inject our "service" into the "action". But sometime we have to use the "servlet". I mean the real servlet, not the struts's action-servlet! For example: We have a servlet

spring学习笔记(21)编程式事务配置,service层概念引入

访问数据库事务导入 在我之前的文章<spring学习笔记(19)mysql读写分离后端AOP控制实例>中模拟数据库读写分离的例子,在访问数据库时使用的方法是: public <E> E add(Object object) { return (E) getSessionFactory().openSession().save(object); } 通过直接开启session而后保存对象.查询数据等操作,是没有事务的.而如果我们的项目规模变大,业务逻辑日益复杂,我们在一个方法中进行大

spring声明式事务,service层必须在ioc容器中声明?

问题描述 各位,小弟在学习spring+hibernate 声明式事务时,发现一个问题, 做了两种测试1. 建立一个普通的 java projectx.y.services 包下有 applicationContext.xml, DefaultFooService.java, 在applicationContext.xml中对DefaultFooService进行声明式事务,并注入 DefaultFooService运行后成功实现事务管理2. 建立一个 web dynamic project在a

spring事务回滚只能配在service层吗。为什么我想在Test中添加事务不能进行回滚呢

问题描述 spring事务回滚只能配在service层吗.为什么我想在Test中添加事务不能进行回滚呢 <tx:advice id="txAdvice2" transaction-manager="txManager"> <tx:attributes> <tx:method name="inserttwo*" propagation="REQUIRED"/> </tx:attribut

在使用spring的过程中,service层写在配置文件中好呢还是注解配置好呢?

问题描述 在使用spring的过程中,service层写在配置文件中好呢还是注解配置好呢? 在使用spring的过程中,service层写在配置文件中好呢还是注解配置好呢?在配置文件中是这样的注解配置时这样的@Service(""userService"")说说理由哦. 解决方案 一般应用性开发使用注解就可以.它较xml配置方式的优势在于省去了xml复杂的配置,而且不需要维护两套内容(xml配置方式需要维护service类和xml文件).但是如果需要修改相关内容,注

急急急!Struts2+spring+ibatis+oracle service层事务不能回滚,请高手指点

问题描述 事务配置<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/sche

使用Spring邮件抽象层发送简单邮件

Spring提供了一个发送电子邮件的高级抽象层,它向用户屏蔽了底层邮件系统的一些细节,同时负责低层次的代表客户端的资源处理.Spring邮件抽象层的主要包为org.springframework.mail.它包括了发送电子邮件的主要接口MailSender和 封装了简单邮件的属性如from, to,cc, subject, text的值对象叫做SimpleMailMessage. 1.我们定义一个发送邮件的接口:OrderManager.java 1 public interface Order

spring在MVC层解决JPA的缓迟加载问题

作为EJB3.0的一部分,JPA是一个好东西.其简单的配置方式及强大的默认配置支持,使其可以轻松自由的存在于轻量与重量之间,如果现在您的JavaEE项目,不管是选择轻量级构架还是重量级构架,如果持久层不选择使用JPA,而是用一些ORM框架(如Hibernate.TopLink)的专用API,那么在将来的某一天一定会为这个选择而说出至尊宝那句"假如上天再给我一个机会-"的至理名言.下面是一个简单的Entity,是对一个CMS系统中,关于树状信息目录实体类的定义,包括了一些详细的映射的配置