spring + hibernate set不允许保存

时间:2010-04-21 08:35:42

标签: java hibernate spring

我可以在休眠中设置任何参数,以便临时不允许持久保存但只允许只读(临时)吗?我可以在applicationcontext.xml中设置吗?

3 个答案:

答案 0 :(得分:3)

Hibernate有一个方法Session.setReadOnly(Object persited, boolean readOnly),允许您将持久化对象标记为只读。

Hibernate 3.5还有Session.setDefaultReadOnly(boolean),可用于将会话检索的所有对象设置为只读。

接下来的挑战是找到一种在Session创建的SessionFactory实例上设置此属性的方法。我想AOP可以用来代理LocalSessionFactoryBean来拦截创建的SessionFacotory实例,将大多数方法委托给原始实例,但是拦截openSession(...)方法。但我对弹簧AOP并不熟悉,IMO很快就会变得很难理解。这是一个直接的方法:

首先,将LocalSessionFactoryBean包装在自定义实现中:

<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>

然后将此类添加到您的代码库中。 (即使使用AOP,您也需要引入一些自定义代码。)

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;
        }
    }
}

只需进行此更改,您的代码的其余部分可以不加修改地运行,并且每次都将获得只读的SessionFactory。如果您想绝对确定没有对数据库进行写操作,则可以覆盖写入数据库的方法,例如saveOrUpdateupdate,虽然我不确定这是否真的有必要。

答案 1 :(得分:1)

您可以将交易标记为readOnly:

@Transactional(readOnly=true)

当我忘记制作事务方法时,我观察到的一个副作用是没有插入或更新,只选择。您可以尝试完全省略事务声明。

您也可以尝试:

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

(或session.setFlushMode(FlushMode.NEVER)

如果这不起作用,您可以使用spring AOP包装DAO调用,并且仅在设置了自定义配置属性的情况下继续执行persist方法。

答案 2 :(得分:1)

我会在数据库级别处理该问题并将应用程序配置为在演示期间使用具有只读权限的用户(使用特定用户进行演示或更改当前使用的权限)。简单,有效,并保证以最小的努力工作。