Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transaction setReadOnly #3495

Merged
merged 5 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,13 @@ public void initTransIfRequired() {
persistCascade = transaction.isPersistCascade();
}

/**
* Mark the underlying transaction as not being query only.
*/
public void markNotQueryOnly() {
transaction.markNotQueryOnly();
}

/**
* Return the type of this request. One of INSERT, UPDATE, DELETE, UPDATESQL or CALLABLESQL.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public int executeOrmUpdate(Update<?> update, Transaction t) {
private int executeOrQueue(PersistRequest request) {
try {
request.initTransIfRequired();
request.markNotQueryOnly();
int rc = request.executeOrQueue();
request.commitTransIfRequired();
return rc;
Expand Down Expand Up @@ -383,6 +384,7 @@ public void update(EntityBean entityBean, Transaction t) {
req.checkDraft();
try {
req.initTransIfRequiredWithBatchCascade();
req.markNotQueryOnly();
if (req.isReference()) {
// its a reference so see if there are manys to save...
if (req.isPersistCascade()) {
Expand Down Expand Up @@ -430,6 +432,7 @@ public void insert(EntityBean bean, InsertOptions insertOptions, Transaction t)
}
try {
req.initTransIfRequiredWithBatchCascade();
req.markNotQueryOnly();
insert(req);
req.resetDepth();
req.commitTransIfRequired();
Expand Down Expand Up @@ -562,6 +565,7 @@ private int deleteRequest(PersistRequestBean<?> req, PersistRequestBean<?> draft
}
try {
req.initTransIfRequiredWithBatchCascade();
req.markNotQueryOnly();
int rows = delete(req);
if (draftReq != null) {
// delete the 'draft' bean ('live' bean deleted first)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,10 @@ public final void depthReset() {
@Override
public final void markNotQueryOnly() {
this.queryOnly = false;
// if the transaction is readonly, it should not allow updates/deletes
if (localReadOnly){
throw new IllegalStateException("This transaction is read-only");
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package org.tests.transaction;

import io.ebean.DB;
import io.ebean.Transaction;
import io.ebean.xtest.BaseTestCase;
import org.junit.jupiter.api.Test;
import org.tests.model.basic.Country;
import org.tests.model.basic.Customer;
import org.tests.model.basic.OrderDetail;
import org.tests.model.basic.ResetBasicData;

import java.util.Arrays;

import static org.assertj.core.api.Assertions.assertThatThrownBy;

public class TestTransactionReadOnly extends BaseTestCase {

@Test
public void testReadOnlyTransactionWithUpdateQuery() {

ResetBasicData.reset();

try (Transaction txn = DB.beginTransaction()) {
txn.setReadOnly(true);

assertThatThrownBy(() -> DB.update(Customer.class).set("name", "Rob2").where().eq("name", "Rob").update())
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("This transaction is read-only");

assertThatThrownBy(() -> DB.sqlUpdate("update o_customer set name = ? where name = ?")
.setParameter(1, "Rob2")
.setParameter(2, "Rob").execute())
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("This transaction is read-only");

assertThatThrownBy(() -> DB.createUpdate(Customer.class, "update customer set name = ? where name = ?")
.setParameter(1, "Rob2")
.setParameter(2, "Rob").execute())
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("This transaction is read-only");

Customer customer = DB.find(Customer.class).where().eq("name", "Rob").findOne();
customer.setName("Rob2");
assertThatThrownBy(() -> DB.save(customer))
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("This transaction is read-only");

txn.commit();
}

}

@Test
public void testReadOnlyTransactionWithDeleteQuery() {

ResetBasicData.reset();

try (Transaction txn = DB.beginTransaction()) {
txn.setReadOnly(true);

assertThatThrownBy(() -> DB.find(OrderDetail.class).where().eq("id", 1).delete())
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("This transaction is read-only");

assertThatThrownBy(() -> DB.sqlUpdate("delete o_order_detail where id = ?")
.setParameter(1, 1).execute())
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("This transaction is read-only");

assertThatThrownBy(() -> DB.createUpdate(OrderDetail.class, "delete o_order_detail where id = ?")
.setParameter(1, 1).execute())
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("This transaction is read-only");

OrderDetail orderDetail = DB.find(OrderDetail.class).where().eq("id", 1).findOne();
assertThatThrownBy(() -> DB.delete(orderDetail))
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("This transaction is read-only");

assertThatThrownBy(() -> DB.deleteAll(Arrays.asList(orderDetail)))
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("This transaction is read-only");

txn.commit();
}

}

@Test
public void testReadOnlyTransactionWithInsertQuery() {

ResetBasicData.reset();

try (Transaction txn = DB.beginTransaction()) {
txn.setReadOnly(true);

Country country = new Country();
country.setName("Germany");
country.setCode("DE");

assertThatThrownBy(() -> DB.save(country))
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("This transaction is read-only");

assertThatThrownBy(() -> DB.saveAll(country))
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("This transaction is read-only");

assertThatThrownBy(() -> DB.insert(country))
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("This transaction is read-only");

assertThatThrownBy(() -> DB.insertAll(Arrays.asList(country)))
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("This transaction is read-only");

txn.commit();
}

}

}