diff --git a/briar-api/src/org/briarproject/api/db/DatabaseComponent.java b/briar-api/src/org/briarproject/api/db/DatabaseComponent.java
index 5609844f42a6c8337dbdc0b30d07b894c2b93773..06800e1c4c57e90d24f38d47edc8af33e3c0b172 100644
--- a/briar-api/src/org/briarproject/api/db/DatabaseComponent.java
+++ b/briar-api/src/org/briarproject/api/db/DatabaseComponent.java
@@ -39,6 +39,21 @@ public interface DatabaseComponent {
 	/** Waits for any open transactions to finish and closes the database. */
 	void close() throws DbException, IOException;
 
+	/** Starts a new transaction and returns an object representing it. */
+	Transaction startTransaction() throws DbException;
+
+	/**
+	 * Aborts the given transaction - no changes made during the transaction
+	 * will be applied to the database.
+	 */
+	void abortTransaction(Transaction txn);
+
+	/**
+	 * Commits the given transaction - all changes made during the transaction
+	 * will be applied to the database.
+	 */
+	void commitTransaction(Transaction txn) throws DbException;
+
 	/**
 	 * Stores a contact associated with the given local and remote pseudonyms,
 	 * and returns an ID for the contact.
diff --git a/briar-api/src/org/briarproject/api/db/Transaction.java b/briar-api/src/org/briarproject/api/db/Transaction.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ea803b05ef888bc1cfe7602ee4b734c937fe79a
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/db/Transaction.java
@@ -0,0 +1,15 @@
+package org.briarproject.api.db;
+
+/** A wrapper around a database transaction. */
+public class Transaction {
+
+	private final Object txn;
+
+	public Transaction(Object txn) {
+		this.txn = txn;
+	}
+
+	public Object unbox() {
+		return txn;
+	}
+}
diff --git a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
index dcf88660af85e9858c356f3fca910d7e790e0b96..b62f180902efa827fcdbb6e31cfb138a809c9c4a 100644
--- a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
+++ b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
@@ -14,6 +14,7 @@ import org.briarproject.api.db.NoSuchLocalAuthorException;
 import org.briarproject.api.db.NoSuchMessageException;
 import org.briarproject.api.db.NoSuchTransportException;
 import org.briarproject.api.db.StorageStatus;
+import org.briarproject.api.db.Transaction;
 import org.briarproject.api.event.EventBus;
 import org.briarproject.api.event.GroupAddedEvent;
 import org.briarproject.api.event.GroupRemovedEvent;
@@ -77,6 +78,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 			Logger.getLogger(DatabaseComponentImpl.class.getName());
 
 	private final Database<T> db;
+	private final Class<T> txnClass;
 	private final EventBus eventBus;
 	private final ShutdownManager shutdown;
 	private final AtomicBoolean closed = new AtomicBoolean(false);
@@ -84,9 +86,10 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 	private volatile int shutdownHandle = -1;
 
 	@Inject
-	DatabaseComponentImpl(Database<T> db, EventBus eventBus,
+	DatabaseComponentImpl(Database<T> db, Class<T> txnClass, EventBus eventBus,
 			ShutdownManager shutdown) {
 		this.db = db;
+		this.txnClass = txnClass;
 		this.eventBus = eventBus;
 		this.shutdown = shutdown;
 	}
@@ -116,6 +119,18 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 		db.close();
 	}
 
+	public Transaction startTransaction() throws DbException {
+		return new Transaction(db.startTransaction());
+	}
+
+	public void abortTransaction(Transaction txn) {
+		db.abortTransaction(txnClass.cast(txn.unbox()));
+	}
+
+	public void commitTransaction(Transaction txn) throws DbException {
+		db.commitTransaction(txnClass.cast(txn.unbox()));
+	}
+
 	public ContactId addContact(Author remote, AuthorId local)
 			throws DbException {
 		T txn = db.startTransaction();
@@ -975,7 +990,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 
 	public void setVisibleToContact(ContactId c, GroupId g, boolean visible)
 			throws DbException {
-		boolean wasVisible = false;
+		boolean wasVisible;
 		T txn = db.startTransaction();
 		try {
 			if (!db.containsContact(txn, c))
diff --git a/briar-core/src/org/briarproject/db/DatabaseModule.java b/briar-core/src/org/briarproject/db/DatabaseModule.java
index 9ac531c0775312fd735d2127144f616646e1394d..6a050ed44b9a449fc8d2e5f5ec461ef749f61043 100644
--- a/briar-core/src/org/briarproject/db/DatabaseModule.java
+++ b/briar-core/src/org/briarproject/db/DatabaseModule.java
@@ -51,7 +51,8 @@ public class DatabaseModule extends AbstractModule {
 	@Provides @Singleton
 	DatabaseComponent getDatabaseComponent(Database<Connection> db,
 			EventBus eventBus, ShutdownManager shutdown) {
-		return new DatabaseComponentImpl<Connection>(db, eventBus, shutdown);
+		return new DatabaseComponentImpl<Connection>(db, Connection.class,
+				eventBus, shutdown);
 	}
 
 	@Provides @Singleton @DatabaseExecutor
diff --git a/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java b/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java
index 70a9113f23c5de966476e7efbb867f0d94236bc7..178dee5b6a9a6730fe16dc3fe3ba00ac52c770f8 100644
--- a/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java
+++ b/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java
@@ -106,9 +106,10 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 				StorageStatus.ACTIVE);
 	}
 
-	private <T> DatabaseComponent createDatabaseComponent(Database<T> database,
+	private DatabaseComponent createDatabaseComponent(Database<Object> database,
 			EventBus eventBus, ShutdownManager shutdown) {
-		return new DatabaseComponentImpl<T>(database, eventBus, shutdown);
+		return new DatabaseComponentImpl<Object>(database, Object.class,
+				eventBus, shutdown);
 	}
 
 	@Test