2016-10-07 4 views
6

Проблема:Как я могу запросить конкретное соединение из com.mchange.v2.c3p0.ComboPooledDataSource?

  • Программа использует com.mchange.v2.c3p0.ComboPooledDataSource для подключения к серверу Sybase
  • Программа выполняет 2 метода, runSQL1() и runSQL2(), в последовательности
  • runSQL1() выполняет SQL, который создает #temptable

    SELECT * INTO #myTemp FROM TABLE1 WHERE X=2 
    
  • runSQL2() выполняет SQL, который читает из этого #tem ptable

    SELECT * FROM #myTemp WHERE Y=3 
    
  • ПРОБЛЕМА: runSQL2() получает передал другое соединение DB из пула, чем тот передал runSQL1().

    Однако Sybase #temptables являются специфичными для подключения, поэтому runSQL2() не удается найти таблицу.

Самое очевидное решение, которое я могу думать (кроме вырожденной сделать размер пула 1, в какой момент мы даже не нужен бассейн), это как-то вспомнить, какие именно соединения из пула было используется runSQL1() и имеет runSQL2() запрос такое же соединение.

Есть ли способ сделать это в com.mchange.v2.c3p0.ComboPooledDataSource?

Если возможно, я бы хотел получить ответ, совместимый с параллельным доступом (другими словами, если соединение, используемое в runSQL1(), используется другим потоком, вызов runSQL2() для подключения будет ждать, пока соединение выдается другим потоком).

Однако, если это невозможно, я в порядке с ответом, который предполагает, что соединения БД (те, которые мне интересны) происходят в одном потоке, и поэтому любое соединение, запрошенное runSQL2(), будет на 100% доступный, если он был доступен для запускаSQL1().

Я также приветствую любые решения, которые решают проблему по-другому, если они не включают «прекратить использование #temptables» как часть решения.

+0

Почему вы не можете запросить соединение перед запуском part1, а затем передать это как параметр для обоих вызовов? – Ivan

+0

@ivan сделал это. Но мне не нравится это решение, поэтому я хотел бы узнать, как получить конкретное соединение вместо – DVK

+1

Я также считаю, что решение, предложенное @Ivan, является правильным решением. Чтобы получить его каким-либо другим способом, вам необходимо сохранить хотя бы идентификатор соединения при его первом его получении. После этого вам нужно использовать отражение в менеджерах пулов и найти подходящее соединение. Вместо того, чтобы делать это, просто придерживаться ссылки на конкретное соединение является более чистым. Если вам действительно нужно это сделать, запросив идентификатор, вы можете написать свой собственный менеджер соединений с оболочкой и использовать его. – Kaan

ответ

0

Самый простой и понятный способ сделать это - просто запросить соединение из пула, а затем запустить runSQL1() и runSQL2() с этим соединением. Модель использования, предлагаемая в вопросе, идет вразрез с общими принципами проектирования диспетчеров пулов соединений, поскольку она эффективно продвигает их к определенному менеджеру транзакций.

Есть Java-фреймворки, которые могут помочь в вышеупомянутом. Например, весной @Transaction или TransactionTemplate можно использовать для разграничения границ транзакций, и это гарантирует, что одно соединение используется одним потоком (точнее, в соответствии с аннотациями распространения транзакций). Spring может использовать множество менеджеров транзакций, но, вероятно, самым простым было бы использовать DataSourceTransactionManager, а также можно было бы использовать c3p0 как DataSource.