问题
Hei there, I'm working on a Primefaces 5/JSF 2/Mybatis webapp. My question is. To know each time who did what (on the app) we have to execute a method setUser(...). The company I'm working in right now, had a C# version of the app we are building now but there were no connection pools there so they only had to execute that procedure when the user logged in.
(right now we just call that method in the getSQLFactory method, which I know is not best practice... but that looked like the only viable solution to not add it manually in all our 200+ Mappers)
public static SqlSessionFactory getSqlSessionFactory() {
HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
ManagedNavUtils navyUtils = (ManagedNavUtils) session.getAttribute("navy");
if (navyUtils != null && navyUtils.getLoggedInUser() != null)
setLoggedInUser(navyUtils.getLoggedInUser());
return factory;
}
IS there a way to call the procedure each time something gets executed on the DB?
my mybatis-config.xml file with the relevant configuration:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
<!-- CONNECTION POOLING PROPERTIES -->
<property name="poolMaximumActiveConnections" value="20" />
<property name="poolMaximumIdleConnections" value="5" />
<property name="poolPingEnabled" value="false" />
</dataSource>
</environment>
</environments>
回答1:
You can create mybatis plugin to intercept all queries.
But for your case better option is to set user only once that is during connection retrieval. Some connection pools allows custom initialization when connection is borrowed from the pool. Another possible option is to wrap DataSource
which is used by mybatis.
For your case that is using datasource shipped with mybatis the easiest way it to wrap DataSource
using custom DataSourceFactory
.
First extend PooledDataSource
like this:
class MyPooledDataSource extends PooledDataSource {
// all constructors should be defined but omitted for brevity
public Connection getConnection() throws SQLException {
Connection connection = super.getConnection();
setLoggedInUser(connection);
return connection;
}
public Connection getConnection(String username, String password) throws SQLException {
Connection connection = super.getConnection(username, password);
setLoggedInUser(connection);
return connection;
}
private void setLoggedInUser(Connection connection) {
// actual setting of logged in user
}
}
Then you need to define factory:
public class MyDataSourceFactory extends PooledDataSourceFactory {
public MyDataSourceFactory() {
this.dataSource = new MyPooledDataSource();
}
}
And modify mybatis-config.xml
to make mybatis use your datasource factory:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="org.myproject.MyDataSourceFactory">
<property name="driver" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
<!-- CONNECTION POOLING PROPERTIES -->
<property name="poolMaximumActiveConnections" value="20" />
<property name="poolMaximumIdleConnections" value="5" />
<property name="poolPingEnabled" value="false" />
</dataSource>
</environment>
</environments>
来源:https://stackoverflow.com/questions/25442075/connection-pool-call-a-procedure-each-time-an-operation-is-made