views:

208

answers:

1

I have a POJO mapped with Hibernate for persistence. In my mapping I specify the following:

<class name="ExpertiseArea">
    <id name="id" type="string">
        <generator class="assigned" />
    </id>
    <version name="version" column="VERSION" unsaved-value="null" />
    <property name="name" type="string" unique="true" not-null="true" length="100" />
    ...
</class>

And I want to test that if I set a name longer than 100 characters, the change won't be persisted. I have a DAO where I save the entity with the following code:

public T makePersistent(T entity){
    transaction = getSession().beginTransaction();
    transaction.begin();

    try{
        getSession().saveOrUpdate(entity);
        transaction.commit();
    }catch(HibernateException e){
        logger.debug(e.getMessage());
        transaction.rollback();
    }   
    return entity;
}

Actually the code above is from a GenericDAO which all my DAOs inherit from. Then I created the following test:

public void testNameLengthMustBe100orLess(){
    ExpertiseArea ea = new ExpertiseArea(
        "1234567890" +
        "1234567890" +
        "1234567890" +
        "1234567890" +
        "1234567890" +
        "1234567890" +
        "1234567890" +
        "1234567890" +
        "1234567890" +
        "1234567890");

    assertTrue("Name should be 100 characters long", ea.getName().length() == 100);

    ead.makePersistent(ea);
    List<ExpertiseArea> result = ead.findAll();
    assertEquals("Size must be 1", result.size(),1);

    ea.setName(ea.getName()+"1234567890");
    ead.makePersistent(ea);

    ExpertiseArea retrieved = ead.findById(ea.getId(), false);
    assertTrue("Both objects should be equal", retrieved.equals(ea));
    assertTrue("Name should be 100 characters long", (retrieved.getName().length() == 100));
}

The object is persisted ok. Then I set a name longer than 100 characters and try to save the changes, which fails:

14:12:14,608  INFO StringType:162 - could not bind value '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' to parameter: 2; data exception: string data, right truncation
14:12:14,611  WARN JDBCExceptionReporter:100 - SQL Error: -3401, SQLState: 22001
14:12:14,611 ERROR JDBCExceptionReporter:101 - data exception: string data, right truncation
14:12:14,614 ERROR AbstractFlushingEventListener:324 - Could not synchronize database state with session
org.hibernate.exception.DataException: could not update: [com.exp.model.ExpertiseArea#33BA7E09-3A79-4C9D-888B-4263314076AF]

//Stack trace

14:12:14,615 DEBUG GenericDAO:87 - could not update: [com.exp.model.ExpertiseArea#33BA7E09-3A79-4C9D-888B-4263314076AF]
14:12:14,616 DEBUG JDBCTransaction:186 - rollback
14:12:14,616 DEBUG JDBCTransaction:197 - rolled back JDBC Connection

That's expected behavior. However when I retrieve the persisted object to check if its name is still 100 characters long, the test fails.

The way I see it, the retrieved object should have a name that is 100 characters long, given that the attempted update failed. The last assertion fails because the name is 110 characters long now, as if the ea instance was indeed updated.

What am I doing wrong here?

+1  A: 

It appears that the object is first stored in the session (and cached) and on failure it is not evicted. You you'd have to session.evict(..) it. Other options are session.clear(..) and session.refresh(..) to make sure you are working with what's in the database.

What you have is a database restriction, no hibernate. If you don't want to hit the database at all, you can use Hibernate Validator's @Length annotation. (Here is a fresh article)

Bozho
Thanks for the explanation and the suggestion on using Hibernate Validators. I'm accepting this answer as accepted.
Cesar