为啥这个 Hibernate MySQL 连接是只读的?

Posted

技术标签:

【中文标题】为啥这个 Hibernate MySQL 连接是只读的?【英文标题】:Why this Hibernate MySQL Connection is read-only?为什么这个 Hibernate MySQL 连接是只读的? 【发布时间】:2011-06-06 14:21:15 【问题描述】:

我有一个在 mysql 数据库上使用 Spring 和 Hibernate 的应用程序。出于某种原因,截至最近几天,每当我尝试将任何对象持久保存到我的数据库时,我都会收到以下错误:

java.sql.SQLException:连接是只读的。导致数据修改的查询是 不允许。*

我一生都无法弄清楚为什么会发生这种情况。几天前我的应用程序运行良好。

我正在我的 applicationContext.xml 文件中配置一个 SessionFactory 对象,如下所示:

     <bean id="sessionFactory" lass="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
         <property name="configLocation"
 value="classpath:/hibernate.cfg.xml"/>
         <property name="packagesToScan">
             <list>
                 <value>com.domain.domainObjects</value>
             </list>
         </property>
     </bean>

我的 hibernate.cfg.xml 文件如下所示:

<?xml version='1.0' encoding='utf-8'?>

<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- Database connection settings -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://url to db:3306/db name</property>
        <property name="connection.username">db user</property>
        <property name="connection.password">db password</property>
        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">10</property>
        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <!-- Enable Hibernate's automatic session context management >
        <property name="current_session_context_class">thread</property-->
        <!-- Disable the second-level cache  -->
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>
        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">update</property>

    </session-factory>
</hibernate-configuration>

我使用的是 mysql/j 连接版本 5.1、hibernate 版本 3.2、spring mvc 3.0.5

【问题讨论】:

配置看起来不错。请添加一个受此影响的示例代码。此外,如果您能指定 MySQL 驱动程序的确切版本,那就太好了。 你在使用事务注解吗?是否设置为@Transactional(readOnly = true) 经过大约 3 小时可怕的调试后,我现在知道发生了什么。我有一个服务级别的方法,我也有一个“周围”的建议。服务级别方法使用@Transactional(readOnly=true) 进行注释,但是,我的建议中有另一个服务使用@Transactional(readOnly=false) 进行注释。我的方面(或建议)使用与普通服务层相同的 DAO 对象,因此当我调用 sessionFactory.getCurrenctSession() 时,它会将为我的只读服务级别方法创建的会话返回给我。现在,我必须重新架构。感谢您的回复! @ElGuapo 请关闭问题。 【参考方案1】:

经过大约 3 个小时的可怕调试,我现在知道发生了什么。我有一个服务级别的方法,我也有一个“周围”的建议。服务级别方法用@Transactional(readOnly=true) 注释,但是,我的建议中有另一个服务annotated with @Transactional(readOnly=false)

我的方面(或建议)使用与我的正常服务层相同的 DAO 对象,因此当我调用 sessionFactory.getCurrenctSession() 时,它会返回为我的只读服务级别方法创建的会话。现在,我必须重新架构。

【讨论】:

我们遇到了完全相同的情况。我们有一个 readOnly=true 方法 M1,它封装了对另一个方法 M2 的调用,即 readOnly=false。有趣的是,我们只是在某些时候看到这个,我不太清楚。【参考方案2】:

这看起来像他们在 MySQL Connector/J 中对于 5.1.6 以下版本的错误: http://bugs.mysql.com/bug.php?id=38747

确保该版本至少为 5.1.7

【讨论】:

以上答案是一个架构问题,即使我的服务同时具有交易类型且没有自定义建议,此解决方案也能帮助我。

以上是关于为啥这个 Hibernate MySQL 连接是只读的?的主要内容,如果未能解决你的问题,请参考以下文章

Spring上的DBCP和Hibernate,不会重新打开死连接,为啥?

为啥hibernate会创建一个连接表和一个连接列?

为啥 Hibernate 文档建议将连接表用于一对多关系?

为啥我们的 Spring/Hibernate/JDBC/Websphere 系统中的连接过早关闭?

为啥 Hibernate 会为 @ManyToOne 关联的隐式连接生成 CROSS JOIN?

为啥hibernate关闭连接后h2的数据库文件仍然会被锁定一段时间?