@@ -1,6 +1,7 @@ | |||
/* | |||
* Copyright 2004-2011 H2 Group. | |||
* Copyright 2011 James Moger. | |||
* Copyright 2012 Frederic Gaillard. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
@@ -68,6 +69,9 @@ public class Db { | |||
private DbUpgrader dbUpgrader = new DefaultDbUpgrader(); | |||
private final Set<Class<?>> upgradeChecked = Collections.synchronizedSet(new HashSet<Class<?>>()); | |||
private boolean skipCreate; | |||
private boolean autoSavePoint = true; | |||
static { | |||
TOKENS = Collections.synchronizedMap(new WeakIdentityHashMap<Object, Token>()); | |||
DIALECTS = Collections.synchronizedMap(new HashMap<String, Class<? extends SQLDialect>>()); | |||
@@ -563,6 +567,11 @@ public class Db { | |||
} | |||
Savepoint prepareSavepoint() { | |||
// don't change auto-commit mode. | |||
// don't create save point. | |||
if (!autoSavePoint) { | |||
return null; | |||
} | |||
// create a savepoint | |||
Savepoint savepoint = null; | |||
try { | |||
@@ -731,4 +740,33 @@ public class Db { | |||
JdbcUtils.closeSilently(stat); | |||
} | |||
} | |||
/** | |||
* Allow to enable/disable globally createIfRequired in TableDefinition. | |||
* For advanced user wanting to gain full control of transactions. | |||
* Default value is false. | |||
* @param skipCreate | |||
*/ | |||
public void setSkipCreate(boolean skipCreate) { | |||
this.skipCreate = skipCreate; | |||
} | |||
public boolean getSkipCreate() { | |||
return this.skipCreate; | |||
} | |||
/** | |||
* Allow to enable/disable usage of save point. | |||
* For advanced user wanting to gain full control of transactions. | |||
* Default value is false. | |||
* @param autoSavePoint | |||
*/ | |||
public void setAutoSavePoint(boolean autoSavePoint) { | |||
this.autoSavePoint = autoSavePoint; | |||
} | |||
public boolean getAutoSavePoint() { | |||
return this.autoSavePoint; | |||
} | |||
} |
@@ -1,7 +1,7 @@ | |||
/* | |||
* Copyright 2004-2011 H2 Group. | |||
* Copyright 2011 James Moger. | |||
* Copyright 2012 Frédéric Gaillard. | |||
* Copyright 2012 Frederic Gaillard. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
@@ -839,6 +839,10 @@ public class TableDefinition<T> { | |||
} | |||
TableDefinition<T> createIfRequired(Db db) { | |||
// globally enable/disable check of create if required | |||
if (db.getSkipCreate()) { | |||
return this; | |||
} | |||
if (!createIfRequired) { | |||
// skip table and index creation | |||
// but still check for upgrades |
@@ -28,6 +28,9 @@ import com.iciql.IciqlException; | |||
import com.iciql.test.models.CategoryAnnotationOnly; | |||
import com.iciql.test.models.ProductAnnotationOnlyWithForeignKey; | |||
/** | |||
* Tests of Foreign Keys. | |||
*/ | |||
public class ForeignKeyTest { | |||
/** |
@@ -1,6 +1,6 @@ | |||
/* | |||
* Copyright 2011 James Moger. | |||
* Copyright 2012 Frédéric Gaillard. | |||
* Copyright 2012 Frederic Gaillard. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
@@ -93,7 +93,7 @@ import com.iciql.util.Utils; | |||
@SuiteClasses({ AliasMapTest.class, AnnotationsTest.class, BooleanModelTest.class, ClobTest.class, | |||
ConcurrencyTest.class, EnumsTest.class, ModelsTest.class, PrimitivesTest.class, | |||
RuntimeQueryTest.class, SamplesTest.class, UpdateTest.class, UpgradesTest.class, JoinTest.class, | |||
UUIDTest.class, ViewsTest.class, ForeignKeyTest.class }) | |||
UUIDTest.class, ViewsTest.class, ForeignKeyTest.class, TransactionTest.class }) | |||
public class IciqlSuite { | |||
private static final TestDb[] TEST_DBS = { |
@@ -0,0 +1,119 @@ | |||
/* | |||
* Copyright 2012 Frederic Gaillard. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.iciql.test; | |||
import static org.junit.Assert.assertEquals; | |||
import java.sql.SQLException; | |||
import org.junit.After; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import com.iciql.Db; | |||
import com.iciql.IciqlException; | |||
import com.iciql.test.models.CategoryAnnotationOnly; | |||
import com.iciql.test.models.ProductAnnotationOnlyWithForeignKey; | |||
/** | |||
* Tests of transactions. | |||
*/ | |||
public class TransactionTest { | |||
/** | |||
* This object represents a database (actually a connection to the | |||
* database). | |||
*/ | |||
private Db db; | |||
@Before | |||
public void setUp() { | |||
db = IciqlSuite.openNewDb(); | |||
// tables creation | |||
db.from(new CategoryAnnotationOnly()); | |||
db.from(new ProductAnnotationOnlyWithForeignKey()); | |||
startTransactionMode(); | |||
} | |||
@After | |||
public void tearDown() { | |||
endTransactionMode(); | |||
db.dropTable(ProductAnnotationOnlyWithForeignKey.class); | |||
db.dropTable(CategoryAnnotationOnly.class); | |||
db.close(); | |||
} | |||
@Test | |||
public void testTransaction() { | |||
// insert in 2 tables inside a transaction | |||
// insertAll don't use save point in this transaction | |||
db.insertAll(CategoryAnnotationOnly.getList()); | |||
db.insertAll(ProductAnnotationOnlyWithForeignKey.getList()); | |||
// don't commit changes | |||
try { | |||
db.getConnection().rollback(); | |||
} catch (SQLException e) { | |||
throw new IciqlException(e, "Can't rollback"); | |||
} | |||
ProductAnnotationOnlyWithForeignKey p = new ProductAnnotationOnlyWithForeignKey(); | |||
long count1 = db.from(p).selectCount(); | |||
CategoryAnnotationOnly c = new CategoryAnnotationOnly(); | |||
long count2 = db.from(c).selectCount(); | |||
// verify changes aren't committed | |||
assertEquals(count1, 0L); | |||
assertEquals(count2, 0L); | |||
} | |||
/** | |||
* Helper to set transaction mode | |||
*/ | |||
private void startTransactionMode() { | |||
db.setSkipCreate(true); | |||
db.setAutoSavePoint(false); | |||
try { | |||
db.getConnection().setAutoCommit(false); | |||
} catch (SQLException e) { | |||
throw new IciqlException(e, "Could not change auto-commit mode"); | |||
} | |||
} | |||
/** | |||
* Helper to return to initial mode | |||
*/ | |||
private void endTransactionMode() { | |||
try { | |||
db.getConnection().setAutoCommit(true); | |||
} catch (SQLException e) { | |||
throw new IciqlException(e, "Could not change auto-commit mode"); | |||
} | |||
// returns to initial states | |||
db.setSkipCreate(false); | |||
db.setAutoSavePoint(true); | |||
} | |||
} |