Version Info:
Hibernate 3.2.6GA
Spring 2.5.5
JUnit 4.4.
Name and version of the database you are using:
Oracle 10G
Mapping documents:
Classes in question:
Code:
public class Requisition {
@Id @GeneratedValue(generator="increment")
@Column(name="REQ_NUMBER")
private Integer requisitionNumber;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="REQ_TYPE", referencedColumnName="VALUE")
private RequisitionType requisitionType;
@Column(name="USER_ID")
private String userId;
@OneToMany(mappedBy="requisition", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
private List<RequisitionOrder> orders;
etc.
Code:
public class RequisitionOrder {
@Id @GeneratedValue(generator="increment")
@Column(name = "ORDER_NUMBER")
private Integer orderNumber;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "REQ_NUMBER")
private Requisition requisition;
@Column(name = "REQ_STATUS")
private String status;
etc.
Test class:
Code:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath*:context/core-context.xml", "/context/orders/testRequisition-context.xml"})
@TransactionConfiguration(transactionManager="txManager", defaultRollback=true)
@Transactional
public class TestRequisitionOrder {
@Resource
private SessionFactory sessionFactory;
@Resource
private RequisitionDao requisitionDao;
@Resource
private RequisitionOrderDao requisitionOrderDao;
@Resource
private LoginUserDao loginUserDao;
@Resource
private RequisitionTypeDao requistionTypeDao;
//Test objects
@Resource
private RequisitionType testRequisitionTypeA;
@Resource
private RequisitionType testRequisitionTypeB;
@Resource
private Requisition testRequisitionA;
@Resource
private Requisition testRequisitionB;
@Resource
private LoginUser testUserA;
@Before
public void setUpTestDataWithinTransaction() throws Exception{
// set up test data within the transaction
testUserA.setActiveDate(new Date());
loginUserDao.save(testUserA);
requistionTypeDao.save(testRequisitionTypeA);
requistionTypeDao.save(testRequisitionTypeB);
requisitionDao.save(testRequisitionA);
requisitionDao.save(testRequisitionB);
}
@Test
public void testFindById(){
RequisitionOrder order = requisitionOrderDao.findByID(requisitionOrderDao.getHighestID());
Assert.assertEquals("TEST ORDER C", order.getReason());
}
@Test
public void testFindByStatus(){
List<RequisitionOrder> orders = requisitionOrderDao.findByStatus("O");
Assert.assertEquals(1, orders.size());
List<String> statuses = new ArrayList<String>();
statuses.add("O");
statuses.add("R");
List<RequisitionOrder> orders2 = requisitionOrderDao.findByStatus(statuses);
Assert.assertEquals(2, orders2.size());
}
The issue:In the Unit test I'm creating some fake requisitions with orders that are configured as spring beans in XML. I am then taking these objects and saving them before the test, and rolling them back after each test, so that no data is committed inside of it.
In the test I have above, the first case works fine. The following SQL is generated to set up my test objects before I call "findById" in my test:
Code:
Hibernate: insert into REQUISITION_TYPES (DESCRIPTION, NAME, VALUE) values (?, ?, ?)
Hibernate: insert into REQUISITION_TYPES (DESCRIPTION, NAME, VALUE) values (?, ?, ?)
Hibernate: insert into REQUISITION_TABLE (REQ_TYPE, USER_ID, REQ_NUMBER) values (?, ?, ?)
Hibernate: insert into REQUISITION_ORDER_TABLE (ADJUSTMENT, COMPLETE_DATE, COST, ORDERED_DATE, OVERHEAD, REASON, RECONCILED_DATE, REQ_NUMBER, REQ_STATUS, TOTAL_COST, ORDER_NUMBER) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into REQUISITION_ORDER_TABLE (ADJUSTMENT, COMPLETE_DATE, COST, ORDERED_DATE, OVERHEAD, REASON, RECONCILED_DATE, REQ_NUMBER, REQ_STATUS, TOTAL_COST, ORDER_NUMBER) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into REQUISITION_TABLE (REQ_TYPE, USER_ID, REQ_NUMBER) values (?, ?, ?)
Hibernate: insert into REQUISITION_ORDER_TABLE (ADJUSTMENT, COMPLETE_DATE, COST, ORDERED_DATE, OVERHEAD, REASON, RECONCILED_DATE, REQ_NUMBER, REQ_STATUS, TOTAL_COST, ORDER_NUMBER) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
And the test passes as expected.
However, on the second test, the following SQL is generated:
Code:
Hibernate: insert into REQUISITION_TYPES (DESCRIPTION, NAME, VALUE) values (?, ?, ?)
Hibernate: insert into REQUISITION_TYPES (DESCRIPTION, NAME, VALUE) values (?, ?, ?)
Hibernate: insert into REQUISITION_TABLE (REQ_TYPE, USER_ID, REQ_NUMBER) values (?, ?, ?)
Hibernate: insert into REQUISITION_TABLE (REQ_TYPE, USER_ID, REQ_NUMBER) values (?, ?, ?)
Hibernate: update REQUISITION_ORDER_TABLE set ADJUSTMENT=?, COMPLETE_DATE=?, COST=?, ORDERED_DATE=?, OVERHEAD=?, REASON=?, RECONCILED_DATE=?, REQ_NUMBER=?, REQ_STATUS=?, TOTAL_COST=? where ORDER_NUMBER=?
Hibernate: update REQUISITION_ORDER_TABLE set ADJUSTMENT=?, COMPLETE_DATE=?, COST=?, ORDERED_DATE=?, OVERHEAD=?, REASON=?, RECONCILED_DATE=?, REQ_NUMBER=?, REQ_STATUS=?, TOTAL_COST=? where ORDER_NUMBER=?
Hibernate: update REQUISITION_ORDER_TABLE set ADJUSTMENT=?, COMPLETE_DATE=?, COST=?, ORDERED_DATE=?, OVERHEAD=?, REASON=?, RECONCILED_DATE=?, REQ_NUMBER=?, REQ_STATUS=?, TOTAL_COST=? where ORDER_NUMBER=?
The problem here is that rather than inserting new orders under the requisition, it's trying to update a non-existent one. The second test fails as a result. Can anyone explain why this is happening?
It seems like hibernate thinks the orders are already persisted (even though the previous transaction was rolled back) and is then trying to update it instead of inserting a new one. What I don't understand is why the same thing doesn't happen with the requisition itself. Something to do with the cascade perhaps?
If I put these two tests in separate class files with the same @Before and context config, everything works fine.
Also should note that I'm relatively new to writing unit tests so if I'm making some huge design mistake please let me know.
Thanks,
Tim