То, как действительно обнаруживают ту транзакцию, было уже запущено?

Так как мне потребовалось некоторое время, чтобы понять это, я подумал, что было бы полезно опубликовать мое решение, используя Java 7+ ZipFileSystem

 openZip(runFile);

 addToZip(filepath); //loop construct;  

 zipfs.close();

 private void openZip(File runFile) throws IOException {
    Map<String, String> env = new HashMap<>();
    env.put("create", "true");
    env.put("encoding", "UTF-8");
    Files.deleteIfExists(runFile.toPath());
    zipfs = FileSystems.newFileSystem(URI.create("jar:" + runFile.toURI().toString()), env);    
 }

 private void addToZip(String filename) throws IOException {
    Path externalTxtFile = Paths.get(filename).toAbsolutePath();
    Path pathInZipfile = zipfs.getPath(filename.substring(filename.lastIndexOf("results"))); //all files to be stored have a common base folder, results/ in my case
    if (Files.isDirectory(externalTxtFile)) {
        Files.createDirectories(pathInZipfile);
        try (DirectoryStream<Path> ds = Files.newDirectoryStream(externalTxtFile)) {
            for (Path child : ds) {
                addToZip(child.normalize().toString()); //recursive call
            }
        }
    } else {
        // copy file to zip file
        Files.copy(externalTxtFile, pathInZipfile, StandardCopyOption.REPLACE_EXISTING);            
    }
 }
27
задан xelurg 26 November 2008 в 05:10
поделиться

6 ответов

Сохраните возвращаемое значение beginTransaction () в Zend_Registry и проверьте его позже.

2
ответ дан Imran 14 October 2019 в 14:35
поделиться

Сделайте попытку/выгоду: если исключение - то, что транзакция уже запустилась (на основе кода ошибки или сообщения строки, безотносительно), продолжить. Иначе выдайте исключение снова.

4
ответ дан 14 October 2019 в 14:35
поделиться

Фреймворк не может знать, начали ли вы транзакцию. Вы даже можете использовать $db->query('START TRANSACTION'), о котором фреймворк не знает, потому что он не анализирует выполняемые вами операторы SQL.

Суть в том, что приложение отслеживает, начали ли вы транзакцию или нет. Это не то, что фреймворк может сделать.

Я знаю, что некоторые фреймворки пытаются это сделать, и делают такие вещи, как подсчет, например, подсчитывают, сколько раз вы начали транзакцию, только разрешая ее, когда вы сделали коммит или откатили соответствующее количество раз. Но это полностью фиктивно, потому что ни одна из ваших функций не может знать, будет ли это делать коммит или откат, или они находятся на другом уровне вложенности.

(Можете ли вы сказать, что я обсуждал это несколько раз?: -)

edit: Propel - это библиотека доступа к базе данных PHP, которая поддерживает Концепция «внутренней транзакции», которая не фиксируется, когда вы говорите это. Начало транзакции только увеличивает счетчик, а фиксация / откат уменьшает счетчик. Ниже приведена выдержка из ветки списка рассылки, где я опишу несколько сценариев, в которых он терпит неудачу.


Нравится вам это или нет, транзакции являются «глобальными» и не подчиняются объектно-ориентированной инкапсуляции.

Проблемный сценарий № 1

Я звоню commit(), зафиксированы ли мои изменения? Если я работаю внутри «внутренней транзакции», это не так. Код, управляющий внешней транзакцией, может откатиться, и мои изменения будут отклонены без моего ведома или контроля.

Например:

  1. Модель A: начать транзакцию
  2. Модель A: выполнить некоторые изменения
  3. Модель B: начать транзакцию (без вывода сообщений)
  4. Модель B: выполнить некоторые изменения
  5. Модель B: зафиксировать (без вывода сообщений)
  6. Модель A: откат (отменяет как изменения модели A, так и изменения модели B)
  7. Модель B: WTF !? Что случилось с моими изменениями?

Сценарий проблемы # 2

Внутренняя транзакция откатывается, она может отменить допустимые изменения, сделанные внешней транзакцией. Когда элемент управления возвращается во внешний код, он считает, что его транзакция все еще активна и доступна для принятия. С вашим патчем они могли бы вызвать commit(), и поскольку transDepth теперь равен 0, он молча установил бы $transDepth в -1 и вернул true, после того, как ничего не фиксировал.

Проблемный сценарий № 3

Если я вызываю commit() или rollback(), когда нет активной транзакции, он устанавливает $transDepth в -1. Следующий beginTransaction() увеличивает уровень до 0, что означает, что транзакцию нельзя ни откатить, ни зафиксировать. Последующие вызовы commit() просто уменьшат транзакцию до -1 или более, и вы никогда не сможете выполнить коммит, пока не сделаете еще один лишний beginTransaction(), чтобы снова увеличить уровень.

По сути, попытка управлять транзакциями в логике приложения, не позволяя базе данных вести бухгалтерский учет, является обреченной идеей. Если для двух моделей требуется использовать явное управление транзакциями в одном запросе приложения, необходимо открыть два соединения с БД, по одному для каждой модели. Тогда каждая модель может иметь собственную активную транзакцию, которая может быть зафиксирована или откатана независимо друг от друга.

(см. http://www.nabble.com/Zend-Framework-Db-Table-ORM-td19691776.html )

25
ответ дан Bill Karwin 14 October 2019 в 14:35
поделиться

Вы также можете написать свой код следующим образом:

try {
    Zend_Registry::get('database')->beginTransaction();
} 
catch (Exception $e) { }

try {
    $totals = self::calculateTotals($Cart);

    $PaymentInstrument = new PaymentInstrument;
    $PaymentInstrument->create();
    $PaymentInstrument->validate();
    $PaymentInstrument->save();

    Zend_Registry::get('database')->commit();
    return true;
} 
catch (Zend_Exception $e) {
    Bootstrap::$Log->err($e->getMessage());
    Zend_Registry::get('database')->rollBack();
    return false;
}
1
ответ дан Adeel 14 October 2019 в 14:35
поделиться

Используйте Zend Profiler, чтобы видеть начало как текст запроса, а Zend_Db_Prfiler :: TRANSACTION как тип запроса без коммита или отката в качестве текста запроса. (Предполагая, что в вашем приложении нет запроса -> («START TRANSACTION») и Zend Profiler)

0
ответ дан siva kiran 14 October 2019 в 14:35
поделиться

Рассмотрение Zend_Db, а также адаптеров (и mysqli и версии PDO) я действительно не вижу хорошего способа проверить состояние транзакции. Кажется, существует выпуск ZF относительно этого - к счастью, с патчем, намеченным для выхода скоро.

В настоящее время, если Вы скорее не выполнили неофициальный код ZF, , в mysqli документации говорится, что Вы можете SELECT @@autocommit, чтобы узнать, ли Вы в настоящее время находитесь в транзакции (допустите ошибку... не в режиме автоматической фиксации).

2
ответ дан Sean McSomething 14 October 2019 в 14:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: