First Draft - BAEL-4122 - A Quick Guide to Autocommit in JDBC

This commit is contained in:
gjohnson 2021-07-23 01:00:45 +01:00
parent 17814a1468
commit 91bbabd97a
2 changed files with 310 additions and 0 deletions

View File

@ -0,0 +1,51 @@
package com.baeldung.jdbcautocommit;
public class Person {
private Integer id;
private String name;
private String lastName;
private Integer age;
public Person() {
}
public Person(Integer id, String name, String lastName, Integer age) {
this.id = id;
this.name = name;
this.lastName = lastName;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}

View File

@ -0,0 +1,259 @@
package com.baeldung.jdbcautocommit;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
public class AutoCommitUnitTest {
private static final String INSERT_PERSON_SQL = "INSERT INTO Person VALUES (?,?,?,?)";
private static final String SELECT_ALL_PEOPLE_SQL = "SELECT * FROM Person";
private static final String UPDATE_PERSON_AGE_BY_ID_SQL = "UPDATE Person SET age = ? WHERE id = ?";
private static final String DELETE_ALL_PEOPLE_SQL = "DELETE FROM Person";
private static final String UPDATE_PERSON_AGE_BY_NAME_SQL
= "UPDATE Person SET age = ? WHERE id = (SELECT id FROM Person WHERE name = ?)";
private static final String CREATE_PERSON_TABLE_SQL
= "CREATE TABLE Person (id INTEGER not null, name VARCHAR(50), lastName VARCHAR(50), age INTEGER, PRIMARY KEY (id))";
private static Connection connection1;
private static Connection connection2;
@BeforeAll
static void setup() throws SQLException {
connection1 = DriverManager.getConnection("jdbc:h2:mem:autocommit", "sa", "");
createPersonTable(connection1);
connection2 = DriverManager.getConnection("jdbc:h2:mem:autocommit", "sa", "");
}
@Test
void givenAutoCommitTrue_whenInsertAndUpdateRecord_thenDataPersistedAfterEachWithoutCommit() throws SQLException {
connection1.setAutoCommit(true);
Person person = new Person(1, "John", "Doe", 45);
insertPerson(connection1, person);
// no explicit commit needed here when auto-commit true
// viewed from different connection, connection2 : assert person has been persisted into
// the database
List<Person> people = selectAllPeople(connection2);
assertThat("person record inserted OK into empty table", people.size(), is(equalTo(1)));
Person personInserted = people.iterator().next();
assertThat("id correct", personInserted.getId(), is(equalTo(1)));
// update age for person in database
updatePersonAgeById(connection1, 1, 65);
// no explicit commit needed here
// viewed from connection2 : assert person's age has been updated to database
people = selectAllPeople(connection2);
Person personUpdated = people.iterator().next();
assertThat("updated age correct", personUpdated.getAge(), is(equalTo(65)));
}
@Test
void givenAutoCommitFalse_whenInsertCommitAndUpdateCommit_thenDataViewableAfterEachCommit() throws SQLException {
connection1.setAutoCommit(false);
Person person = new Person(1, "John", "Doe", 45);
insertPerson(connection1, person);
// viewed from different connection, connection2 : assert that person has not yet been
// persisted to database before issuing commit
List<Person> people = selectAllPeople(connection2);
assertThat("No people have been inserted into database yet", people.size(), is(equalTo(0)));
connection1.commit();
// viewed from connection2 : assert that person has been persisted to database after
// issuing commit
people = selectAllPeople(connection2);
assertThat("Person has been inserted into empty table after commit", people.size(), is(equalTo(1)));
Person personInserted = people.iterator().next();
assertThat("id correct", personInserted.getId(), is(equalTo(1)));
updatePersonAgeById(connection1, 1, 65);
// assert that person's age has not been updated before issuing commit
people = selectAllPeople(connection2);
Person personUpdated = people.iterator().next();
assertThat("person's age still 45, not updated", personUpdated.getAge(), is(equalTo(45)));
connection1.commit();
// viewed from connection2 : assert that person's age has been updated after issuing commit
people = selectAllPeople(connection2);
personUpdated = people.iterator().next();
assertThat("person's age updated to 65", personUpdated.getAge(), is(equalTo(65)));
}
@Test
void givenAutoCommitFalse_whenInsertAndUpdateWithCommitOnlyAtEnd_thenDataOnlyViewableAfterCommit() throws SQLException {
connection1.setAutoCommit(false);
Person person = new Person(1, "John", "Doe", 45);
insertPerson(connection1, person);
// viewed from different connection, connection2 : assert that person has not yet been
// persisted to database before issuing commit
List<Person> people = selectAllPeople(connection2);
assertThat("No people have been inserted into database yet", people.size(), is(equalTo(0)));
updatePersonAgeById(connection1, 1, 65);
// viewed from connection2 : assert that person has still not yet been
// persisted to database before issuing commit
people = selectAllPeople(connection2);
assertThat("No people have been inserted into database yet", people.size(), is(equalTo(0)));
connection1.commit();
// viewed from connection2 : assert that person record has been persisted to
// database and person's age has been updated after issuing commit
people = selectAllPeople(connection2);
Person personUpdated = people.iterator().next();
assertThat("person's age updated to 65", personUpdated.getAge(), is(equalTo(65)));
}
@Test
void givenAutoCommitTrue_whenUpdateWithNestedSelect_thenUpdatePersistedWithoutCommit() throws SQLException {
connection1.setAutoCommit(true);
Person person = new Person(1, "John", "Doe", 45);
insertPerson(connection1, person);
updatePersonAgeByName(connection1, "John", 77);
// viewed from connection2 : assert person's age has been updated correctly to database
// without issuing commit
List<Person> people = selectAllPeople(connection2);
Person personUpdated = people.iterator().next();
assertThat("updated age correct", personUpdated.getAge(), is(equalTo(77)));
}
@Test
void givenAutoCommitFalse_whenModeChangedToTrueAfterSQLUpdate_thenUpdatePersistedWithoutCommit() throws SQLException {
connection1.setAutoCommit(false);
Person person = new Person(1, "John", "Doe", 45);
insertPerson(connection1, person);
updatePersonAgeByName(connection1, "John", 77);
connection1.setAutoCommit(true);
// viewed from connection2 : assert record inserted and person's age has been updated
// correctly to database after auto-commit changed false -> true ... without explicit commit needed
List<Person> people = selectAllPeople(connection2);
Person personUpdated = people.iterator().next();
assertThat("updated age correct", personUpdated.getAge(), is(equalTo(77)));
}
@AfterEach
void deleteAllRecords() throws SQLException {
if (connection1.getAutoCommit() == false) {
connection1.setAutoCommit(true);
}
deleteAllPeople(connection1);
}
@AfterAll
static void closeConnections() throws SQLException {
connection1.close();
connection2.close();
}
private static void createPersonTable(Connection connection) throws SQLException {
try(Statement statement = connection.createStatement()) {
statement.executeUpdate(CREATE_PERSON_TABLE_SQL);
}
}
private static int insertPerson(Connection connection, Person person) throws SQLException {
try (PreparedStatement preparedStatement = connection.prepareStatement(INSERT_PERSON_SQL)) {
preparedStatement.setInt(1, person.getId());
preparedStatement.setString(2, person.getName());
preparedStatement.setString(3, person.getLastName());
preparedStatement.setInt(4, person.getAge());
// execute statement and return the number of rows inserted
return preparedStatement.executeUpdate();
}
}
private static void deleteAllPeople(Connection connection) throws SQLException {
try (Statement statement = connection.createStatement()) {
statement.execute(DELETE_ALL_PEOPLE_SQL);
}
}
private static List<Person> selectAllPeople(Connection connection) throws SQLException {
List<Person> people = null;
try (Statement statement = connection.createStatement()) {
people = new ArrayList<>();
ResultSet resultSet = statement.executeQuery(SELECT_ALL_PEOPLE_SQL);
while (resultSet.next()) {
Person person = new Person();
person.setId(resultSet.getInt("id"));
person.setName(resultSet.getString("name"));
person.setLastName(resultSet.getString("lastName"));
person.setAge(resultSet.getInt("age"));
people.add(person);
}
}
return people;
}
private static void updatePersonAgeById(Connection connection, int id, int newAge) throws SQLException {
try (PreparedStatement preparedStatement = connection.prepareStatement(UPDATE_PERSON_AGE_BY_ID_SQL)) {
preparedStatement.setInt(1, newAge);
preparedStatement.setInt(2, id);
preparedStatement.executeUpdate();
}
}
private static void updatePersonAgeByName(Connection connection, String name, int newAge) throws SQLException {
try (PreparedStatement preparedStatement = connection.prepareStatement(UPDATE_PERSON_AGE_BY_NAME_SQL)) {
preparedStatement.setInt(1, newAge);
preparedStatement.setString(2, name);
preparedStatement.executeUpdate();
}
}
}