Search code examples
javaoracle11gjpa-2.0junit4spring-boot-test

@Temporal annotation does not work when used with @Transactional JUnit tests


I have a simple CRUD operations with Spring Boot and Oracle 11g My Entity class looks like:

public class Entity{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int entity_id;
...
@CreationTimestamp
@Column(name = "creation_date", columnDefinition="ON UPDATE CURRENT_TIMESTAMP")
@Temporal(TemporalType.TIMESTAMP)
private Date creation_date;

...//setters and getters
}

My JUnit looks like

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class EntityTests {
Logger log = Logger.getAnonymousLogger();

@Autowired
private EntityRepository  entityRepository;

@Test
public void addEntity(){
    Entity entity= new Entity();
    entity.setFirst_name("Jhon");
    entity.setLast_name("David");
    Entity savedEntity = entityRepository.save(entity);
    log.info(savedEntity.toString());
    Assert.assertEquals(entity, savedEntity);
    //log.info(savedEntity.getCreation_date().toString());
}

The last log.info throws NullPointerException when run with @Transactional annotation, But works fine otherwise and DB gets populated with expected values.

Is that how @Transactional behaves or Hibernate does not insert any value for Dates in transactional JUnits?


Solution

  • Because you are using @Transactional annotation on your class, all you changes are not committed into DB. @CreationTimestamp and `@Temporal(TemporalType.TIMESTAMP)' will not work until changes will be committed.

    What you can do:

    Do not use @Transactional in functional test using DB. If you removed annotation your method will be not rollbacked after end of method, so you have to create @After method with cleaning up you stuff created by tests:

    @After
    public void cleanUp() {
        entityRepository.deleteAll();
    }
    

    Second option is to change your save method to saveAndFlush. Also you can do this after you saved entity by calling entityRepository.flush() method, but here you have to fetch your entity from repository once more time:

    entityRepository.save(entity);
    entityRepository.flush();
    Entity savedEntity = entityRepository.findOne(id);