【问题标题】:Spring/Hibernate Write operations are not allowed in read-only mode只读模式下不允许 Spring/Hibernate 写操作
【发布时间】:2015-03-14 13:04:55
【问题描述】:

我已经阅读了有关同一主题的其他一些问题,但就我而言,我实际上并没有指定任何内容。让我真正感到困惑的是我还有另一个有效的电话。我没有指定任何交易,所以我不确定为什么这会成为一个问题。

当我尝试使用 xssSave()(在底部的服务类中)时会发生这种情况,但 sqlInject(也在同一个类中)工作正常。据我所知,这些操作相同,只是一个有效,一个无效。

如果您想查看完整代码和/或自行检查,请访问 GitHub (https://github.com/tenmilez/WebBilly)。

Spring配置(分成3个文件):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--
    <import resource="recipeasy-aspects.xml" />
    -->
    <import resource="webbilly-data.xml"/>
    <import resource="webbilly-spring.xml"/>
    <import resource="webbilly-service.xml"/>


    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <bean id="simpleUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="order">
            <value>0</value>
        </property>
        <property name="mappings">
            <props>
                <prop key="welcome.htm">welcomeController</prop>
                <prop key="sqli.htm">SQLiController</prop>
                <prop key="xss.htm">XssController</prop>
            </props>
        </property>
    </bean>

    <bean id="paramResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
        <property name="paramName" value="method"/>
        <property name="defaultMethodName" value="onInitPage"/>
    </bean>

    <bean id="welcomeController" class="com.webbilly.web.WelcomeController"/>

    <bean id="SQLiController" class="com.webbilly.web.SQLiController">
        <property name="methodNameResolver" ref="paramResolver"/>
        <property name="sqliServices" ref="sqliServices"/>
    </bean>

    <bean id="XssController" class="com.webbilly.web.XssController">
        <property name="methodNameResolver" ref="paramResolver"/>
        <property name="sqliServices" ref="sqliServices"/>
    </bean>
</beans>

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="sqliServices" class="com.webbilly.service.SQLiServices">
        <property name="sqliDataDAO" ref="sqliDataDAOhibernate"/>
        <!--
        <property name="sqliDataDAO" ref="sqliDataDAOjdbc" />
        <property name="sqliDataDAO" ref="sqliDataDAOhibernate" />
        -->


        <property name="xssDataDAO" ref="xssDataDAO"/>

    </bean>


</beans>

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="sessionFactory"
          class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="jdbcDataSource"/>
        <property name="mappingDirectoryLocations">
            <value>classpath:/com/webbilly/dao/hibernate/hbm</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
                <prop key="hibernate.dialect">${database.dialect}</prop>
            </props>
        </property>
    </bean>

    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <bean id="genericDAO" class="com.webbilly.dao.hibernate.GenericDAO"
          abstract="true">
        <property name="hibernateTemplate" ref="hibernateTemplate"/>
    </bean>

    <bean id="sqliDataDAOhibernate" parent="genericDAO">
        <constructor-arg>
            <value>com.webbilly.domain.SQLiData</value>
        </constructor-arg>
    </bean>
    <bean id="xssDataDAO" parent="genericDAO">
        <constructor-arg>
            <value>com.webbilly.domain.XssData</value>
        </constructor-arg>
    </bean>

    <bean id="sqliDataDAOjdbc" class="com.webbilly.dao.jdbc.SQLiDAO">
        <property name="dataSource" ref="jdbcDataSource"/>
    </bean>

    <bean id="jdbcDataSource"
          class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${database.driver}"/>
        <property name="url" value="${database.url}"/>
        <property name="username" value="${database.username}"/>
        <property name="password" value="${database.password}"/>
        <property name="connectionProperties">
            <props>
                <prop key="allowMultiQueries">true</prop>
            </props>
        </property>
    </bean>

</beans>

我的数据对象(这些对象有名称吗?总是将它们称为域对象,但我不确定这是否是广泛接受的术语)。

package com.webbilly.domain;

/**
 * Created by christopher on 12/12/14.
 */
public class XssData {

    private int id;
    private String userName;
    private String message;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}


package com.webbilly.domain;

/**
 * Created by christopher on 12/3/14.
 */
public class SQLiData {

    private String id;
    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

持久层

package com.webbilly.dao;

import java.util.Collection;

public interface IGenericDAO<T> {
    void save(T t);

    Collection<T> getAll();

    T getById(int id);

    void delete(int id);
}

package com.webbilly.dao.hibernate;

import com.webbilly.dao.IGenericDAO;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;

import java.util.Collection;

public class GenericDAO<T> extends HibernateDaoSupport implements IGenericDAO<T> {

    /**
     * ******************************************************
     * ********* Accessors and private members ****************
     * *******************************************************
     */

    private Class<T> type;

    public GenericDAO(Class<T> type) {
        this.type = type;
    }

    public T getById(int id) {
        return (T) getHibernateTemplate().get(type, id);
    }

    public Collection<T> getAll() {
        return getHibernateTemplate().loadAll(type);
    }

    public void save(T t) {
        getHibernateTemplate().saveOrUpdate(t);
    }

    public void delete(int id) {
        getHibernateTemplate().delete(getById(id));
    }

}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.webbilly.domain">
    <class name="SQLiData" table="sqli">
        <id column="id" name="id" type="int">
            <generator class="increment"/>
        </id>
        <property name="value" type="string">
            <column name="value"/>
        </property>
    </class>
</hibernate-mapping>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.webbilly.domain">
    <class name="XssData" table="xss">
        <id column="id" name="id" type="int">
            <generator class="increment"/>
        </id>
        <property name="userName" type="string">
            <column name="user_name"/>
        </property>
        <property name="message" type="string">
            <column name="message"/>
        </property>
    </class>
</hibernate-mapping>

服务层(它实际上只是一个类;我的应用程序还没有那么大)。

package com.webbilly.service;

import com.webbilly.dao.IGenericDAO;
import com.webbilly.domain.SQLiData;
import com.webbilly.domain.XssData;

import java.util.Collection;

/**
 * Created by christopher on 12/3/14.
 */
public class SQLiServices {


    private IGenericDAO<SQLiData> sqliDataDAO;
    private IGenericDAO<XssData> xssDataDAO;

    public void sqlInject(String str) {
        SQLiData sqliData = new SQLiData();
        sqliData.setValue(str);
        getSqliDataDAO().save(sqliData);
    }

    public void xssSave(XssData data) {
        xssDataDAO.save(data);
    }

    public Collection<XssData> getAllPosts() {
        return xssDataDAO.getAll();
    }

    public IGenericDAO<SQLiData> getSqliDataDAO() {
        return sqliDataDAO;
    }

    public void setSqliDataDAO(IGenericDAO<SQLiData> sqliDataDAO) {
        this.sqliDataDAO = sqliDataDAO;
    }

    public IGenericDAO<XssData> getXssDataDAO() {
        return xssDataDAO;
    }

    public void setXssDataDAO(IGenericDAO<XssData> xssDataDAO) {
        this.xssDataDAO = xssDataDAO;
    }
}

【问题讨论】:

  • 为什么要编写自己的 DAO 而不是使用 Spring Data?
  • @chrylis 我不熟悉 Spring Data。
  • 它基本上可以让您编写该接口,然后为您生成所有实际代码(以及内置的标准方法,如您指定的方法)。
  • 错误提示您没有使用事务。不需要定义事务管理器:stackoverflow.com/questions/25222341/…
  • @JamesB 这并没有解释为什么它适用于 sqlInject() 方法而不适用于 xssSave() 方法。据我所知,事务管理器是可选的,直到需要管理事务(而且我没有事务)。

标签: java spring hibernate


【解决方案1】:

HibernateTemplate 不管理事务,您需要一个 HibernateTransactionManager 来代替。

写入操作需要在事务的上下文中执行,因此您还需要使用 @Transactional 注释您的 DAO 或您的服务。

【讨论】:

    猜你喜欢
    • 2011-10-12
    • 2011-07-21
    • 1970-01-01
    • 2011-12-01
    • 2014-04-26
    • 1970-01-01
    • 2016-12-12
    • 2014-10-03
    • 2018-01-20
    相关资源
    最近更新 更多