Files
Mitgliederverwaltung/.plans/done/issue-203-missing-database-transactions.md
shahondin1624 0ffc993d3f
Database Portability Tests / Unit Tests (PlatformHelper) (pull_request) Failing after 37s
Database Portability Tests / Integration (mysql) (pull_request) Has been skipped
Database Portability Tests / Integration (postgres) (pull_request) Has been skipped
Database Portability Tests / Integration (sqlite) (pull_request) Has been skipped
Database Portability Tests / Verify no MySQL-specific SQL (pull_request) Successful in 5s
chore: move issue-203 plan to done
2026-04-29 22:09:20 +02:00

1.7 KiB

Issue #203: Missing Database Transactions in MemberService

Problem

The MemberService::create() method inserts a member and its sub-entities (addresses, phones, emails) in separate queries without a transaction:

public function create(array $data, array $addresses = [], ...): array {
    // ...
    $member = $this->memberMapper->insert($member);
    
    $savedAddresses = $this->saveAddresses($member->getId(), $addresses);
    $savedPhones = $this->savePhones($member->getId(), $phones);
    $savedEmails = $this->saveEmails($member->getId(), $emails);
    // ...
}

If savePhones() fails, the member is created but phones are not attached.

Similarly, softDelete() deletes sub-entities separately without a transaction.

Impact

  • Data inconsistency if partial failures occur
  • Orphaned sub-entities on failed member creation
  • Orphaned member on failed sub-entity creation

Solution

Wrap the operation in a transaction:

use OCP\DB\Events\SQLFileEmitter;

public function create(array $data, ...): array {
    $this->db->beginTransaction();
    try {
        $member = $this->memberMapper->insert($member);
        $savedAddresses = $this->saveAddresses($member->getId(), $addresses);
        // ...
        $this->db->commit();
    } catch (\Exception $e) {
        $this->db->rollback();
        throw $e;
    }
}

Tasks

  • Add transaction wrapping to MemberService::create()
  • Add transaction wrapping to MemberService::softDelete()
  • Add transaction wrapping to MemberService::update() (sync operations)
  • Verify rollback works correctly on failure
  • Consider adding a DbTransactionTrait for reusability

Labels

  • bug
  • backend
  • priority:high
  • data-integrity