2012-04-05 1 views
1

Я внедрил ведение журнала базы данных для регистрации определенных деталей в моем приложении веб-портала java для Oracle DB. Для этого я использую пул соединений, чтобы получить соединение и использовать его для вызова jdbc для хранимой процедуры.Уменьшение фиксации и вставка объемных записей за раз в вызове jdbc?

У меня есть статический java-метод logService, который получает объект соединения и вызывает SP. Этот метод logservice вызывается из разных мест моего приложения Java с соответствующими данными, переданными в параметрах, которые inturn передается на вызов SP.

Таким образом, для каждого пользователя, обращающегося к порталу, будет задействовано около 10-20 вызовов метода logservice. Итак, я буду делать 10-20 вызовов SP, и мне приходилось совершать каждый раз, когда я вызываю SP.

Но проблема заключается в том, что мой администратор базы данных рекомендовал не совершать транзакции для каждой транзакции, а inturn совершать все 10-20 транзакций за раз, так как есть высокая частота фиксации, которую он говорит. Как это сделать? Если его неясно, я могу опубликовать образец кода.

Да я уже с фильтром для моего веб-приложения следующим образом,

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 } 
} 
} 

После перенаправлении redirectURL, я звоню logservice из многих мест в моем приложении следующим образом,

DBLog.logService(param1, param2); // static method call 

Этот logservice готовит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?

Фильтр подход -

public class DBLog { 

static Connection con = null; 
    static PreparedStatement stmt = null; 

static { 
     try{ 
     new net.verizon.whatsnext.dblog.JDCConnectionDriver("oracle.jdbc.driver.OracleDriver", 
     "jdbc:oracle:thin:@localhost:7001:xe","user", "password"); 
    con=getConnection(); // Getting connection from Connection pool 

    }catch(Exception e){} 
    } 

public static Connection getConnection() throws SQLException { 
     return DriverManager.getConnection("jdbc:jdc:jdcpool"); 
    } 


public static void logService(String param1, String param2) { 
    ... 
    finally { 
       stmt.close(); 
      } 
    } 

public static void closeTrans() { 

    con.commit(); 
    con.close(); 
    } 
} //End of DBLog class 


public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) { 
    ... 
    finally { 
      DBLog.closeTrans(); 
     } 
    } 

Итак, я закрываю соединение, наконец, после того, как в совершали, наконец, блок в методе doFilter. Я правильно? Это будет работать?

ответ

1

Во-первых, не открывать соединение на каждый запрос, а повторно использовать соединение из пула соединений (возможно, DataSource), и положить в общем пространстве - в вашем случае проще всего использовать статическое поле ThreadLocal.

В Фильтре:

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(); 
    } 
} 

В классе логгера:

public static void logService(String param1, String param2) { 
    Connection conn = getConnection(); // obtain thread-local connection 
    // your database statements go here 
} 

В общем, избегайте использования статики. И, возможно, подумайте над пересмотром своего подхода к протоколированию.

1

Рассмотрите возможность использования транзакции за запрос. Вы можете создать Filter, который открывает транзакцию базы данных перед обработкой запроса и впоследствии ее совершает. Это сделало бы это.

+0

может быть более конкретным плз. –

+0

добавить фильтр на веб-приложение, которые будут обернуть сервлет с открытой сделкой: общественной ничтожной doFilter (ServletRequest REQ, ServletResponse гезр) { попытки { // открытой транзакция здесь filterChain.doFilter (REQ, соответственно) ; } finally { // совершите транзакцию здесь } } – ahanin

+0

Прекрасно .. Но plz подскажет, как зафиксировать в doFilter .. Я добавил дополнительные данные в свой пост выше. –

1

Демонтаж транзакции, как и безопасность и ведение журнала, можно рассматривать как украшение вашего кода.

Допустим, у вас есть интерфейс 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 

Теперь, я просто предлагаю образец здесь. Реализация этого в вашем коде будет зависеть от вашего дизайна, в зависимости от того, как структурирован ваш код.

Дальнейшие ссылки

 Смежные вопросы

  • Нет связанных вопросов^_^