org.hibernate.StaleStateException:批量更新从update [0]返回意外的行数;实际行数:0;预期:1

时间:2014-08-26 12:41:40

标签: java hibernate unit-testing junit batch-processing

我在STS中使用JUnit编写单元测试用例。类是

TestConfiguration.java

 @Configuration
 @ComponentScan("com.kgfsl.collections.core")
 public class TestConfiguration {

@Bean
@Inject
public org.hibernate.SessionFactory sessionFactory(DataSource dataSource) {
    LocalSessionFactoryBuilder sessionBuilder = new  
LocalSessionFactoryBuilder(dataSource);
    sessionBuilder.scanPackages("com.kgfsl.collections.core.models");
    sessionBuilder.addProperties(getHibernateProperties());
    return sessionBuilder.buildSessionFactory();
}

private static Properties getHibernateProperties() {
    final org.hibernate.cfg.Configuration configuration = new
org.hibernate.cfg.Configuration();
    configuration.setProperty(HBM2DDL_AUTO, "create");
    configuration.setProperty(DIALECT, "org.hibernate.dialect.MySQL5Dialect");

    // Test Default settings
    configuration.setProperty(CURRENT_SESSION_CONTEXT_CLASS, "thread");
    configuration.setProperty(USE_GET_GENERATED_KEYS, "true");
    configuration.setProperty(USE_REFLECTION_OPTIMIZER, "true");
    configuration.setProperty(ORDER_UPDATES, "true");
    configuration.setProperty(ORDER_INSERTS, "true");
    configuration.setProperty(USE_NEW_ID_GENERATOR_MAPPINGS, "true");
    return configuration.getProperties();
 }


}

BaseRepositoryTest.java

@RunWith (SpringJUnit4ClassRunner. class)
@ContextConfiguration(classes = {UserManagementTestConfiguration.class})
public abstract class BaseRepositoryTest extends
    AbstractJUnit4SpringContextTests {

@Inject
SessionFactory sessionFactory;

private Transaction transaction;

public Session getSession() {
    Session session;
    try {
        session = sessionFactory.getCurrentSession();
    } catch (SessionException se) {
        session = sessionFactory.openSession();
    }
    return session;
}

@Before
public void setUp() throws Exception {
    transaction = getSession().beginTransaction();
}

@After
public void tearDown() throws Exception {
    if (transaction != null) {
        transaction.rollback();
    }
    getSession().close();
}

@Before
public void baseSetUp() {
    MockitoAnnotations.initMocks(this);
 }
}

UserRoleDaoTest.java

  public class UserRoleDaoTest extends BaseRepositoryTest
 {  
  @Autowired
  private UserRoleDao userroleDao;

 @Test
 public void shouldCreateRole()
 {
    UserRole userRole=new UserRoleBuilder().userroleBuilder(10,"Md Aslam", 
     "N","1").build();

    UserRole userroleCreated=userroleDao.persist(userRole);
    UserRole userroleGet = userroleDao.findById(userroleCreated.getRoleId());
    Assert.assertThat(userroleGet.getRoleName(), Is.is("Md Aslam"));
    Assert.assertThat(userroleGet.getRoleId(), Is.is(10));

    UserRole userroleCreate=userroleDao.persist(userRole);
    Assert.assertNotNull(userRole.getRoleId());
 }

 @Test
 public void shouldGetRoleById()
 {
    UserRole userRole=new UserRoleBuilder().userroleBuilder(10,"Md Aslam",
     "N","1").build();
    UserRole userroleCreated=userroleDao.persist(userRole);
    UserRole userroleGet = userroleDao.findById(userroleCreated.getRoleId());
    assertNotNull(userroleGet);
    Assert.assertThat(userroleGet.getRoleId(), Is.is(10));
    }

 @Test
 public void shouldUpdateAccount()
 {
    UserRole userRole=new UserRoleBuilder().userroleBuilder(10,"aslam",
     "N","1").build();
    UserRole userroleCreated=userroleDao.persist(userRole);

    UserRole userroleGet = userroleDao.findById(userroleCreated.getRoleId());
    Assert.assertEquals(userRole.getRoleId(), userroleGet.getRoleId());
    UserRole userRoleForUpdate=new   
    UserRoleBuilder().userroleBuilder(userroleCreated.getRoleId(),"Md Aslam", 
     "Y","1").build();
    userroleDao.update(userRoleForUpdate);
 } 

@Test
public void shouldGetRoleByName()
{

        UserRole userRole=new UserRoleBuilder().userroleBuilder(10,"aslam",  
          "N","1").build();
        UserRole userroleCreated=userroleDao.persist(userRole);

    UserRole userrolegetbyname=userroleDao.findByRoleName(userRole.getRoleName());
    assertNotNull(userrolegetbyname);

    }

 }

当我运行此类时,它显示错误,如

    shouldGetRoleByName:org.hibernate.StaleStateException: Batch update returned  
    unexpected row count from  Update [0]; actual row count: 0; expected: 1     

shouldGetRoleByName的实际方法是

   public UserRole findByRoleName(String roleName) {
     UserRole userPermission = (UserRole) 
           criteria().setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                .add(eq("roleName", roleName.trim().toLowerCase())).uniqueResult();
        return userPermission;
    }

除了shouldGetRoleByName()这个方法之外,传递测试用例中的所有方法 我试过很多方法,但我无法找到解决方案,如果有人知道解决方案,请帮助我。

2 个答案:

答案 0 :(得分:1)

似乎只有在“shouldGetRoleByName”方法中触发查询时,Hibernate才会保留内存中的所有更改并执行刷新(将更改发送到数据库)。 此时,在“shouldUpdateAccount”中调用的更新被发送到数据库并且它失败(影响零记录)。

尝试在“shouldUpdateAccount”方法的末尾调用“flush”,并检查错误是否移至那里。如果是这样,您可以调查您的代码以更好地了解其行为。请注意,会话中执行的所有实体修改仅在特定时间发送到数据库(例如:当您提交transacion或执行查询时)。

答案 1 :(得分:0)

100%工作解决方案!!!!只是在你的hibernate查询中写save而不是saveOrUpdate ...因为由于以前的日志,你的类生成了一些以前存储在ur表中的其他id,所以hibernate尝试使用相同的id更新,并且它找不到具有该id的行所以它给出了staleStateException。