Hibernate will track changes to any object that is obtained from and still attached to a live Session, and write it out when that Session is closed or the transaction is done.
This is basically the same way JDO would work too.
If you do not want the object saved, you are going to have to cause the transaction to roll back. As you figuredout, this means registering custom exception types, or relying on the default treatment of RuntimeException derived exceptions to cause rollback.
If you really want to use programmatic means to set the current tx to rollback-only, ala EJB, if you are using TransactionInterceptor (ie using the declarative transaction proxies, not TransactionTemplate), you can use:
while an approach that will work for both cases is:
where ptm is the PlatformTransactionManafer instance you are using, i.e. JTATransactionManager or HibernateTransactionManager.
public static void setCurrentTransactionRollbackOnly(PlatformTransactionManager ptm) throws
TransactionDefinition definition = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_MANDATORY);
TransactionStatus status = ptm.getTransaction(definition);