Java 在jdbc调用中一次减少提交和插入批量记录?
我已经实现了数据库日志记录,以便将java weblogic门户应用程序中的某些细节记录到Oracle DB中。 为此,我使用连接池来获取连接,并使用它对存储过程进行jdbc调用 我有一个静态java方法logService,它获取连接对象并调用SP。 这个logservice方法是从java应用程序中的不同位置调用的,并在参数中传递了相关细节,inturn将这些参数传递给SP调用 因此,对于访问门户的每个用户,大约有10-20个logservice方法调用。 因此,我将进行10-20次SP呼叫,每次呼叫SP时我都必须提交 但问题是,我的DBA建议不要每次提交事务,而是一次提交所有10-20个事务,因为提交频率很高。 我如何做到这一点?如果不清楚,我可以发布一个示例代码 是的,我已经为我的web应用程序安装了如下过滤器Java 在jdbc调用中一次减少提交和插入批量记录?,java,oracle,jdbc,Java,Oracle,Jdbc,我已经实现了数据库日志记录,以便将java weblogic门户应用程序中的某些细节记录到Oracle DB中。 为此,我使用连接池来获取连接,并使用它对存储过程进行jdbc调用 我有一个静态java方法logService,它获取连接对象并调用SP。 这个logservice方法是从java应用程序中的不同位置调用的,并在参数中传递了相关细节,inturn将这些参数传递给SP调用 因此,对于访问门户的每个用户,大约有10-20个logservice方法调用。 因此,我将进行10-20次SP呼叫
public final class RequestFilter implements Filter{
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
try {
((HttpServletResponse) response).sendRedirect(redirectUrl);
if (chain != null) {
chain.doFilter(request, response);
}
}
finally { // commit transaction here }
}
}
DBLog.logService(param1, param2); // static method call
在重定向到redirectURL后,我在应用程序的许多地方调用logservice,如下所示:
public final class RequestFilter implements Filter{
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
try {
((HttpServletResponse) response).sendRedirect(redirectUrl);
if (chain != null) {
chain.doFilter(request, response);
}
}
finally { // commit transaction here }
}
}
DBLog.logService(param1, param2); // static method call
此日志服务使用连接池对象准备调用SP。
我只是在下面提供一个简单的示例代码,说明我是如何做的
public static void logService(String param1, String param2) {
try {
con=getConnection();
stmt = con.prepareCall("{call DB_LOG_SP (?, ?}");
stmt.setString(1, param1);
stmt.setString(2, param2);
stmt.execute();
stmt.close();
}finally {
stmt.close();
con.close();
}
}
但是,由于我在SP调用后关闭了连接,如何在doFilter方法内的finally{}块中提交事务
过滤法--
因此,在doFilter方法的finally块中提交后,我将最终关闭连接。
我做得对吗?它会工作吗?考虑对每个请求使用事务。您可以创建在处理请求之前打开数据库事务并在之后提交的。这就可以了。事务性划分,就像安全性和日志记录一样,可以看作是代码的装饰 假设您有一个接口
BusinessTask
,当前所有数据库操作都在实现该接口:
public interface BusinessTask {
public void doWork();
}
例如,您有一个AddSavingsAccountTask
和一个TransferMoneyTask
现在,您可以以这样的方式实现每个任务,即每个任务都单独提交(或回滚)。但是,如果您想创建一个包含创建帐户和立即转账的任务,那么您将遇到麻烦,因为现在您需要更改交易界限
因此,一种方法是定义TransactionDecorator,您可以在其中放置事务划分
public class TransactionDecorator implements BusinessTask{
private final BusinessTask task;
public TransactionDecorator(BusinessTask task){
this.task = task;
}
@Override
public void doWork() {
//beging transaction
task.doWork();
//commit or rollback
}
}
然后,您可以简单地用事务划分来装饰现有任务:
final AddSavingsAccount addSavingsAccountTask = new AddSavingsAccount();
final TransferFunds transferFundsTask = new TransferFunds();
BusinessTask transaction = new TransactionDecorator(new BusinessTask(){
@Override
public void doWork() {
addSavingsAccountTask.doWork();
transferFundsTask.doWork();
}
});
transaction.doWork(); //all the magic happens here
现在,我只是在这里提出一种模式。这在代码中的实现会因设计和代码的结构而有所不同
进一步参考
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
Connection conn = obtainConnection(); // obtain connection and store it ThreadLocal
conn.setAutoCommit(false);
try {
chain.doFilter(request, response);
} finally {
conn.commit();
}
}
在您的logger类中:
public static void logService(String param1, String param2) {
Connection conn = getConnection(); // obtain thread-local connection
// your database statements go here
}
通常,避免使用静力学。可能会考虑重新考虑日志记录的方法。< /P>将一个过滤器添加到Web应用程序中,它将打开Servlet与打开的事务:公共空隙DoFulter(Servlet请求Req,Servlet RealthRESP){Test{{//OpenCurraseFieldLoop.DoFulter(Req,RESP);}最终{//提交事务}}好的但请建议如何在doFilter中提交。。我在上面的帖子中添加了更多的细节。交易划分似乎不错,但我觉得ahanin建议的解决方案似乎对我的案例很有希望。请建议如何在doFilter finally{}方法中提交。Thanks@aa阅读手册:好的。请检查上面贴在标题下的示例代码,-过滤方法--请告诉我是否合适。谢谢