<p dir="auto">I want to know if there is a problem with my transaction manager or is the SQL statement incorrectly written, or is it something else?I hope anyone can give me some hints.</p>
<p dir="auto">The development environment：hibernate+spring</p>
<p dir="auto">Exception:<br>
com.google.common.eventbus.EventBus$LoggingSubscriberExceptionHandler handleException<br>
Could not dispatch event: io.shardingsphere.core.transaction.listener.TransactionListener@5c0a4d7f to public void io.shardingsphere.core.transaction.listener.TransactionListener.listen(io.shardingsphere.core.transaction.event.TransactionEvent) throws java.sql.SQLException</p>
<p dir="auto">My HibernateTransactionManager design:<br>
<a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/bean/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/bean">@bean</a><br>
<a class="user-mention notranslate" data-hovercard-type="organization" data-hovercard-url="/orgs/scope/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/scope">@scope</a>("singleton")<br>
public HibernateTransactionManager transactionManager() {<br>
return new AppTransactionManager();<br>
}</p>
<p dir="auto"><a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/SuppressWarnings/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/SuppressWarnings">@SuppressWarnings</a>("serial")<br>
public final class AppTransactionManager extends HibernateTransactionManager {</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="public boolean isExistingTransaction() {
	Object transaction = doGetTransaction();
	return isExistingTransaction(transaction);
}

@Autowired
@Override
public void setSessionFactory(SessionFactory sessionFactory) {
	super.setSessionFactory(sessionFactory);
}"><pre class="notranslate"><code class="notranslate">public boolean isExistingTransaction() {
	Object transaction = doGetTransaction();
	return isExistingTransaction(transaction);
}

@Autowired
@Override
public void setSessionFactory(SessionFactory sessionFactory) {
	super.setSessionFactory(sessionFactory);
}
</code></pre></div>
<p dir="auto">}</p>
<p dir="auto">sql action log:<br>
com.google.common.eventbus.EventBus$LoggingSubscriberExceptionHandler handleException<br>
Could not dispatch event: io.shardingsphere.core.transaction.listener.TransactionListener@5c0a4d7f to public void io.shardingsphere.core.transaction.listener.TransactionListener.listen(io.shardingsphere.core.transaction.event.TransactionEvent) throws java.sql.SQLException<br>
Hibernate: select playerenti_.id as id1_11_ from player playerenti_ where playerenti_.account=?<br>
2018-08-13 15:30:26,752 [INFO ] [game-BalancingPool-/loginActor-14] Sharding-Sphere-SQL - Rule Type: sharding<br>
2018-08-13 15:30:26,752 [INFO ] [game-BalancingPool-/loginActor-14] Sharding-Sphere-SQL - Logic SQL: select playerenti_.id as id1_11_ from player playerenti_ where playerenti_.account=?<br>
2018-08-13 15:30:26,752 [INFO ] [game-BalancingPool-/loginActor-14] Sharding-Sphere-SQL - SQLStatement: SelectStatement(super=DQLStatement(super=AbstractSQLStatement(type=DQL, tables=Tables(tables=[Table(name=player, alias=Optional.of(playerenti_))]), conditions=Conditions(orCondition=OrCondition(andConditions=[])), sqlTokens=[TableToken(beginPosition=38, skippedSchemaNameLength=0, originalLiterals=player)], parametersIndex=1)), containStar=false, selectListLastPosition=33, groupByLastPosition=0, items=[CommonSelectItem(expression=playerenti_.id, alias=Optional.of(id1_11_))], groupByItems=[], orderByItems=[], limit=null, subQueryStatement=null)<br>
2018-08-13 15:30:26,753 [INFO ] [game-BalancingPool-/loginActor-14] Sharding-Sphere-SQL - Actual SQL: sharding0 ::: select playerenti_.id as id1_11_ from player playerenti_ where playerenti_.account=? ::: [[123]]<br>
2018-08-13 15:30:26,753 [INFO ] [game-BalancingPool-/loginActor-14] Sharding-Sphere-SQL - Actual SQL: sharding1 ::: select playerenti_.id as id1_11_ from player playerenti_ where playerenti_.account=? ::: [[123]]<br>
2018-08-13 15:30:26,753 [INFO ] [game-BalancingPool-/loginActor-14] Sharding-Sphere-SQL - Actual SQL: sharding2 ::: select playerenti_.id as id1_11_ from player playerenti_ where playerenti_.account=? ::: [[123]]<br>
com.google.common.eventbus.EventBus$LoggingSubscriberExceptionHandler handleException<br>
Could not dispatch event: io.shardingsphere.core.transaction.listener.TransactionListener@5c0a4d7f to public void io.shardingsphere.core.transaction.listener.TransactionListener.listen(io.shardingsphere.core.transaction.event.TransactionEvent) throws java.sql.SQLException<br>
com.google.common.eventbus.EventBus$LoggingSubscriberExceptionHandler handleException<br>
Could not dispatch event: io.shardingsphere.core.transaction.listener.TransactionListener@5c0a4d7f to public void io.shardingsphere.core.transaction.listener.TransactionListener.listen(io.shardingsphere.core.transaction.event.TransactionEvent) throws java.sql.SQLException<br>
com.google.common.eventbus.EventBus$LoggingSubscriberExceptionHandler handleException<br>
Could not dispatch event: io.shardingsphere.core.transaction.listener.TransactionListener@5c0a4d7f to public void io.shardingsphere.core.transaction.listener.TransactionListener.listen(io.shardingsphere.core.transaction.event.TransactionEvent) throws java.sql.SQLException<br>
2018-08-13 15:30:26,767 [INFO ] [game-BalancingPool-/loginActor-14] IdWorkerBaseImpl - timestamp:1534145426767,timestampLeftShift:19,nextId:128613326315848704,workerId:1,sequence:0<br>
Hibernate: insert into player (account, active_pass, active_time, ban_end_time, ban_talk_end_time, channel, create_server_id, create_step, device, introduce, mark, nickname, pic_id, pwd, register_time, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)<br>
2018-08-13 15:30:26,865 [INFO ] [game-BalancingPool-/loginActor-14] Sharding-Sphere-SQL - Rule Type: sharding<br>
2018-08-13 15:30:26,865 [INFO ] [game-BalancingPool-/loginActor-14] Sharding-Sphere-SQL - Logic SQL: insert into player (account, active_pass, active_time, ban_end_time, ban_talk_end_time, channel, create_server_id, create_step, device, introduce, mark, nickname, pic_id, pwd, register_time, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)<br>
2018-08-13 15:30:26,865 [INFO ] [game-BalancingPool-/loginActor-14] Sharding-Sphere-SQL - SQLStatement: InsertStatement(super=DMLStatement(super=AbstractSQLStatement(type=DML, tables=Tables(tables=[Table(name=player, alias=Optional.absent())]), conditions=Conditions(orCondition=OrCondition(andConditions=[AndCondition(conditions=[Condition(column=Column(name=id, tableName=player), operator=EQUAL, positionValueMap={}, positionIndexMap={0=15})])])), sqlTokens=[TableToken(beginPosition=12, skippedSchemaNameLength=0, originalLiterals=player), io.shardingsphere.core.parsing.parser.token.InsertValuesToken@2618291e], parametersIndex=16)), columns=[Column(name=account, tableName=player), Column(name=active_pass, tableName=player), Column(name=active_time, tableName=player), Column(name=ban_end_time, tableName=player), Column(name=ban_talk_end_time, tableName=player), Column(name=channel, tableName=player), Column(name=create_server_id, tableName=player), Column(name=create_step, tableName=player), Column(name=device, tableName=player), Column(name=introduce, tableName=player), Column(name=mark, tableName=player), Column(name=nickname, tableName=player), Column(name=pic_id, tableName=player), Column(name=pwd, tableName=player), Column(name=register_time, tableName=player), Column(name=id, tableName=player)], generatedKeyConditions=[], insertValues=InsertValues(insertValues=[InsertValue(type=VALUES, expression=(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?), parametersCount=16)]), columnsListLastPosition=193, generateKeyColumnIndex=-1, insertValuesListLastPosition=250)<br>
2018-08-13 15:30:26,866 [INFO ] [game-BalancingPool-/loginActor-14] Sharding-Sphere-SQL - Actual SQL: sharding0 ::: insert into player (account, active_pass, active_time, ban_end_time, ban_talk_end_time, channel, create_server_id, create_step, device, introduce, mark, nickname, pic_id, pwd, register_time, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ::: [[123, 0, null, null, null, 0, 1, 4, ZDRkMmQwNWVkNDVmMzA4ZDk1ZDI2MmFhZjQyZjU4NTY=, null, 1, null, null, password, 2018-08-13 15:30:26.768, 128613326315848704]]</p>
<p dir="auto">Supporting <code class="notranslate">DISTINCT</code> SQL syntax is on the way.</p>
<p dir="auto">We plan to support <code class="notranslate">DISTINCT</code> SQL syntax.  The following is our thought about <code class="notranslate">DISTINCT</code>, welcome to discuss this solution.</p>
<h5 dir="auto">SQL Usage</h5>
<table role="table">
<thead>
<tr>
<th></th>
<th>None GROUP BY</th>
<th>GROUP BY</th>
</tr>
</thead>
<tbody>
<tr>
<td>Simple SELECT</td>
<td>SELECT DISTINCT price FROM item;</td>
<td>SELECT DISTINCT price FROM item GROUP BY price;</td>
</tr>
<tr>
<td>COUNT()</td>
<td>SELECT COUNT(DISTINCT price) FROM item;</td>
<td>SELECT COUNT(DISTINCT price) FROM item GROUP BY price;</td>
</tr>
<tr>
<td>SUM()</td>
<td>SELECT SUM(DISTINCT price) FROM item;</td>
<td>SELECT SUM(DISTINCT price) FROM item GROUP BY price;</td>
</tr>
<tr>
<td>AVG()</td>
<td>SELECT AVG(DISTINCT price) FROM item;</td>
<td>SELECT AVG(DISTINCT price) FROM item GROUP BY price;</td>
</tr>
<tr>
<td>MIN()</td>
<td>SELECT MIN(DISTINCT price) FROM item;</td>
<td>SELECT MIN(DISTINCT price) FROM item GROUP BY price;</td>
</tr>
<tr>
<td>MAX()</td>
<td>SELECT MAX(DISTINCT price) FROM item;</td>
<td>SELECT MAX(DISTINCT price) FROM item GROUP BY price;</td>
</tr>
</tbody>
</table>
<h5 dir="auto">Processing</h5>
<p dir="auto">The basic processing procedure is as follow:</p>
<blockquote>
<p dir="auto">SQL Parse --&gt; SQL Route --&gt; SQL Rewrite --&gt; SQL Execute --&gt; SQL Merge</p>
</blockquote>
<p dir="auto">Considering those <code class="notranslate">DISTINCT</code> SQL above, we can group those SQL to handle.</p>
<h6 dir="auto">Simple SELECT</h6>
<ol dir="auto">
<li>
<p dir="auto">SQL Parse</p>
<p dir="auto">It is necessary to analyze the <code class="notranslate">DISTINCT</code> token.</p>
</li>
<li>
<p dir="auto">SQL Route</p>
<p dir="auto">To make sure where SQL should be sent to execute.</p>
</li>
<li>
<p dir="auto">SQL Rewrite</p>
<p dir="auto">Rewrite logic SQL to actual SQL. Let us suppose we rewrite logic SQL to 2 actual SQLs:</p>
<blockquote>
<p dir="auto">SELECT DISTINCT price FROM item_0;</p>
<p dir="auto">SELECT DISTINCT price FROM item_1;</p>
</blockquote>
</li>
<li>
<p dir="auto">SQL Execute</p>
<p dir="auto">Send actual SQLs to some of the shardings to execute. Let us suppose that we get two resultsets, r1 and r2 from two shardings.</p>
</li>
<li>
<p dir="auto">SQL Merge</p>
<p dir="auto">To get distinct results from r1 and r2 by  DISTINCT(r1, r2).</p>
</li>
</ol>
<p dir="auto">Therefore, we can get fianl distinct results from all of the shardings.</p>
<h6 dir="auto">COUNT() &amp; SUM()</h6>
<p dir="auto">The processing of COUNT() and SUM() is same, so we take COUNT() for example.</p>
<ol dir="auto">
<li>
<p dir="auto">SQL Parse</p>
<p dir="auto">It is necessary to analyze the <code class="notranslate">DISTINCT</code> token.</p>
</li>
<li>
<p dir="auto">SQL Route</p>
<p dir="auto">To make sure where SQL should be sent to execute.</p>
</li>
<li>
<p dir="auto">SQL Rewrite</p>
<p dir="auto">Rewrite logic SQL to actual SQL. Let us suppose we rewrite logic SQL to 2 actual SQLs:</p>
<blockquote>
<p dir="auto">SELECT DISTINCT price FROM item_0;</p>
<p dir="auto">SELECT DISTINCT price FROM item_1;</p>
</blockquote>
</li>
<li>
<p dir="auto">SQL Execute</p>
<p dir="auto">Send actual SQLs to some of the shardings to execute. Let us suppose that we get two resultsets, r1 and r2 from two shardings.</p>
</li>
<li>
<p dir="auto">SQL Merge</p>
<p dir="auto">To get distinct results r3 from r1 and r2 by DISTINCT(r1, r2), then it is possiable to get final correct <code class="notranslate">COUNT(DISTINCT price) </code>by counting r3.</p>
</li>
</ol>
<p dir="auto">You can find instead of getting  <code class="notranslate">COUNT(DISTINCT price)</code> from shardings and counting those resultsets, we get <code class="notranslate">DISTINCT price</code> from each sharding and distinguish those results again in our procedure. At last, we calculate the <code class="notranslate">COUNT()</code> of TWICE-DISTINCT results. The processing of <code class="notranslate">SUM()</code>  is same with this.</p>
<h6 dir="auto">AVG</h6>
<p dir="auto">Handling <code class="notranslate">AVG</code> is more complex. We need to get <code class="notranslate">SUM(DISTINCT price)</code> and <code class="notranslate">COUNT(DISTINCT price)</code> by using the processing above. After that, we can get <code class="notranslate">AVG(DISTINCT price)</code>  by calculating <code class="notranslate">SUM(DISTINCT price)/COUNT(DISTINCT price)</code>.</p>
<h6 dir="auto">MIN() &amp; MAX()</h6>
<p dir="auto">It is easier to process two of those functions. Here, we take <code class="notranslate">MIN()</code> for example.</p>
<ol dir="auto">
<li>
<p dir="auto">SQL Parse</p>
<p dir="auto">It is necessary to analyze the <code class="notranslate">DISTINCT</code> token.</p>
</li>
<li>
<p dir="auto">SQL Route</p>
<p dir="auto">To make sure where SQL should be sent to execute.</p>
</li>
<li>
<p dir="auto">SQL Rewrite</p>
<p dir="auto">Rewrite logic SQL to actual SQL. Let us suppose we rewrite logic SQL to 2 actual SQLs:</p>
<blockquote>
<p dir="auto">SELECT MIN(DISTINCT price) FROM item_0;</p>
<p dir="auto">SELECT MIN(DISTINCT price) FROM item_1;</p>
</blockquote>
</li>
<li>
<p dir="auto">SQL Execute</p>
<p dir="auto">Send actual SQLs to some of the shardings to execute. Let us suppose that we get two resultsets, r1 and r2 from two shardings.</p>
</li>
<li>
<p dir="auto">SQL Merge</p>
<p dir="auto">To get final <code class="notranslate">MIN(DISTINCT price)</code> result from r1 and r2 by MIN(r1, r2).</p>
</li>
</ol>
<h6 dir="auto">DISTINCT + GROUP BY</h6>
<p dir="auto">Welcome to join us to discuss this processing.</p>
<p dir="auto">Base on the result of the above analysis, we can get the following tasks:</p>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Parding the SQL syntax.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Rewriting the logic SQL containing <code class="notranslate">DISTINCT</code> to the relative actual SQLs correctly.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Executing those actual SQLs</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Merging those resultsets by using corresponding algorithms.</li>
</ul>