views:

314

answers:

3

is there any parameter i can set in hibernate so that temporary not allow persist anything but only allow read only (temporary) ? can i set in applicationcontext.xml?

+1  A: 

You can mark your transaction as readOnly:

@Transactional(readOnly=true)

One side-effect I've observed when one forgets to make a method transactional is that no inserts or updates happen, only selects. You can try omitting the transaction declaration completely.

You can also try:

<prop key="org.hibernate.FlushMode">NEVER</prop>

(or session.setFlushMode(FlushMode.NEVER))

If that doesn't work, you can wrap your DAO calls with spring AOP, and proceed to the persist method only in case a custom configuration property is set.

Bozho
but i do not want to throw error when i call hibernate.updateOrMerge . when this is called, i want it don't do save, and dont return error
cometta
I'm not sure whether it throws an exception
Bozho
there is not hibernate_readonly parameter i can set?
cometta
try the flush mode
Bozho
hmm, u sure? i set <prop key="hibernate.FlushMode">NEVER</prop> and <prop key="org.hibernate.FlushMode">NEVER</prop> , cant work..no error.. it still persist my entity
cometta
did you try the programmatic setting? (session.setFlushMode ?)
Bozho
nope, didnt tried programmatic way, i looking for setting <prop that i can do directly on applicationContext.xml file
cometta
@cometta check my update.
Bozho
+3  A: 

Hibernate has a method Session.setReadOnly(Object persited, boolean readOnly) that allows you to mark a persisted object as read-only.

Hibernate 3.5 has also Session.setDefaultReadOnly(boolean) that can be used to set all objects retrieved by a session to read only.

The challenge then is to find a way of setting this property on the Session instances created by the SessionFactory. I imagine AOP can be used to proxy the LocalSessionFactoryBean to intercept the created SessionFacotory instances, delegating most methods to the original instance, but intercepting theopenSession(...) methods. But I'm not that familiar with spring AOP, and IMO it can quickly become quite hard to understand. Here's a direct approach:

First, wrap your LocalSessionFactoryBean in custom implementation:

<bean name="sessionFactory" class="ReadOnlySessionFactoryBean">
   <constructor-arg>
      <bean class="LocalSessionFactoryBean">
       <!-- your existing session factory bean, 
            all your existing hibernate mappings, properties etc. -->
      </bean>
   </constructor-arg>
</bean>

Then add this class to your codebase. (Even with AOP, you will need to introduce some custom code.)

public class ReadOnlySessionFactoryBean extends AbstractFactoryBean
{
    private AbstractSessionFactoryBean sessionFactoryBean;

    public ReadOnlySessionFactoryBean(AbstractSessionFactoryBean sessionFactoryBean)
    {
        this.sessionFactoryBean = sessionFactoryBean;
    }

    @Override
    public Class getObjectType()
    {
        return sessionFactoryBean.getObjectType();
    }

    @Override
    protected Object createInstance() throws Exception
    {
        SessionFactory factory = sessionFactoryBean.getObject();
        return new WrapSessionFactory(factory);
    }

    static class WrapSessionFactory implements SessionFactory
    {
        private Sessionfactory delegate;

        WrapSessionFactory(SessionFactory delegate)
        {
            this.delegate = delegate;
        }

        // delegate most methods to the delegate SessionFactory

        // override all the openSession(...) methods
        public Session openSession()
        {
            Session session = delegate.openSession();
            session.setDefaultReadOnly(true);
            return session;
        }
    }
}

With just this change, the remainder of your code can run unmodified, and each time will get a read-only SessionFactory. If you wanted to be absolutely sure no writes are being done to the database, you could override the methods that write to the db, e.g. saveOrUpdate, update, although I'm not sure that is really necessary.

mdma
+1  A: 

I would handle that at the database level and configure the application to use a user with read-only permissions during demos (either use a specific user for the demo or change the permissions of the currently used). Simple, effective and guaranteed to work with minimal efforts.

Pascal Thivent