簡體   English   中英

java對已分離的對象進行Hibernate不必要的查詢

[英]java Hibernate unnecessary queries on detached objects

我正在使用hibernate和c3p0連接池插入,更新和刪除許多分離的對象。 問題是hibernate不會批處理語句,而是執行a

select @@session.tx_read_only

每個session.persist / insert / update / delete(object)之間。 分析sql-connection它看起來像這樣:

select @@session.tx_read_only
insert...
select @@session.tx_read_only
insert...
select @@session.tx_read_only
insert...
select @@session.tx_read_only
insert...
select @@session.tx_read_only
insert...
select @@session.tx_read_only

選擇@@ session.tx_rad_only總是返回“0”(當然)。 無論我是使用無狀態會話還是有狀態會話都無關緊要。 由此產生的性能是不可接受的,並且遠非任何期望。

我的Hibernate Konfiguration:

 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:4040/xy?zeroDateTimeBehavior=convertToNull</property>
    <property name="hibernate.connection.username">xy</property>
    <property name="hibernate.connection.password">xy</property>
    <property name="hibernate.connection.autocommit">false</property>
    <property name="hibernate.show_sql">false</property>
    <property name="hibernate.format_sql">false</property>
    <property name="hibernate.use_sql_comments">false</property>
    <property name="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory</property>
    <property name="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property>
    <property name="hibernate.c3p0.min_size">5</property>
    <property name="hibernate.c3p0.max_size">20</property>
    <property name="hibernate.c3p0.timeout">300</property>
    <property name="hibernate.c3p0.max_statements">250</property>
    <property name="hibernate.c3p0.idle_test_period">3000</property>
    <property name="hibernate.jdbc.batch_size">250</property>
    <property name="hibernate.connection.release_mode">auto</property>
    <property name="hibernate.order_inserts">true</property>
    <property name="hibernate.order_updates">true</property>
    <property name="hibernate.cache.use_second_level_cache">false</property>
    <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
    <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
    <property name="hibernate.cache.use_query_cache">true</property>
    <property name="net.sf.ehcache.configurationResourceName">hibernate_ehcache.xml</property>

我正在使用:

<dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-c3p0</artifactId>
        <version>4.3.5.Final</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.31</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>4.3.4.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>ejb3-persistence</artifactId>
        <version>1.0.2.GA</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-ehcache</artifactId>
        <version>4.3.4.Final</version>
    </dependency>

我對hibernate幾乎沒有任何考驗,這是一個很好的猜測我犯了一個大錯誤,所以請隨意提出任何建議。 我切換到休眠,因為ORM功能來自普通的jdbc預處理語句,具有極快的性能。 MYSQL-Server處於良好的配置狀態。

edit1:我知道: Hibernate中不必要的查詢 - MySql我的實體中沒有事務性注釋,也沒有任何定義的隔離級別

edit2:我將我的連接池更改為bonecp - 問題仍然存在。 似乎顯然是一個休眠的配置問題。

edit3:嘗試了許多不同的東西,發現可能有一些提示:如果我manualy session.flush()每5個插入(=批量大小例如)[嘗試批量示例AGAIN來自hibernate], 選擇@@ session。 tx_read_only查詢出現雙倍 - 每5個查詢。 因此,我假設select @@ session.tx_read_only與刷新有關。 有沒有辦法阻止hibernate刷新每一次插入/更新? 我到目前為止嘗試過:session.setFlushMode(FlushMode.COMMIT / NEVER / etc)沒有任何行為變化。 也許我錯誤配置了什么...... hibernate觸發什么來刷新每個插入? 桌上的唯一約束? hibernate驗證框架? 復雜的對象圖? 困難的並發? 也許是一個鎖定問題(Hibernate不確定是否其他人鎖定了表並且沒有批處理,但如果表是只讀的,則檢查每個插入?)?

我發現沒有任何關於這個極端(我認為)沖洗bahaviour。

我們通過在連接字符串中設置useLocalSessionState = true來解決此問題。

下面的鏈接解釋了Mysql5.6和java連接器5.1.23發生的ReadOnly相關更改的詳細信息。 http://dev.mysql.com/doc/relnotes/connector-j/en/news-5-1-23.html

您需要在單個事務中包含所有這些CRUD操作,因此所有語句都在同一個DB連接中執行。

您還可以啟用以下Hibernate配置:

<property name="hibernate.order_inserts" value="true"/>
<property name="hibernate.order_updates" value="true"/>
<property name="hibernate.jdbc.batch_size" value="50"/>

這些查詢並不意味着您沒有批處理。 這是MySQL的事情

某些驅動程序需要特殊的批處理重新排序指令:

<property name="hibernate.connection.url">jdbc:mysql://host:port/db?rewriteBatchedStatements=true</property

我在配置中發現了這個漏洞。 我不得不改變mysql-connectionsstring

<property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:4040/xy?zeroDateTimeBehavior=convertToNull</property>

<property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:4040/xy?rewriteBatchedStatements=true</property>    

這解決了我的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM