这是一个非常简单的测试,用于在数据库中持久保存一个临时Person对象,然后验证该对象是否保存在 数据库与瞬态Person对象相同。 这是测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/daoIntegration-test.xml")
@Transactional
public class HibernatePersonDaoIntegrationTest {
@Autowired
private PersonDao PersonDao;
@Autowired
private SessionFactory sessionFactory;
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
public void shouldSavePerson() {
//Given
Person person = new Person();
//When
PersonDao.savePerson(person);
//Then ----THIS ASSERTION PASSES!!!
assertThat(person.getId(), notNullValue());
//And ----THIS ONE FAILS!!!
Person persistedPerson = jdbcTemplate.queryForObject("select * from table_Person", Person.class);
assertThat(persistedPerson, is(person));
}
我的daoIntegration-test.xml
<jdbc:embedded-database id="dataSource" type="HSQL"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="packagesToScan" value="com.domain"/>
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
域类是:
@Entity
@Table(name="table_Person")
public class Person {
@Id
@TableGenerator(name = "seq_table", table = "GENERATOR_TABLE")
@GeneratedValue(strategy = GenerationType.TABLE, generator = "seq_table")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
private Long id;
private String personFirstName;
...
第一个断言通过,但第二个断言失败了,我在某个地方犯了一个愚蠢的错误,但不知道在哪里!!!
答案 0 :(得分:4)
第二个断言失败只是因为它返回了Person
个对象的不同实例。由于您没有(?)定义equals()
/ hashCode()
,因此is()
匹配器失败。
实现它们(这通常是Hibernate的一个好主意)。
第一个断言通过,因为Hibernate从seq_table
获取了id但尚未刷新实体本身。这意味着该实体位于第一级缓存中,但尚未存在于数据库中。因此,当您使用JDBC直接查询数据库时:
jdbcTemplate.queryForObject("select * from table_Person", Person.class);
找不到记录。保存实体或使用JPA查询对象后调用flush()
。 Hibernate非常聪明,可以在flush()
之前查询。
答案 1 :(得分:1)
您正在执行SELECT *
查询,只有在数据库中有一行时才会返回一个对象。
如果查询没有返回一行,或者没有返回一个对象,则抛出IncorrectResultSizeDataAccessException
。
您确定不会抛出异常吗?
您的Person类是否实现了equals和hashCode correctly?如果is()方法取决于这些,则它不能比你的实现允许的更好。