Resumo : neste tutorial, mostraremos como usar transações JDBC para gerenciar transações no banco de dados SQLite.
Banco de dados de amostra para demonstração de transação
Antes de iniciar com Java, criaremos duas novas tabelas no banco de dados test.db.
- A
materials
tabela armazena o mestre de materiais. - A
inventory
tabela armazena o relacionamento entre a tabelawarehouses
ematerials
. Além disso, ainventory
tabela possui aqty
coluna que armazena os dados do estoque.
As instruções a seguir criam as tabelas materials
e inventory
.
CREATE TABLE IF NOT EXISTS materials (
id integer PRIMARY KEY,
description text NOT NULL
);
CREATE TABLE IF NOT EXISTS inventory (
warehouse_id integer,
material_id integer,
qty real,
PRIMARY KEY (warehouse_id, material_id),
FOREIGN KEY (warehouse_id) REFERENCES warehouses (id),
FOREIGN KEY (material_id) REFERENCES materials (id)
);
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
O diagrama a seguir ilustra as tabelas e seu relacionamento.
O que é uma transação de banco de dados
Uma transação representa um conjunto de operações executadas como uma única unidade de trabalho. Isso significa que se alguma operação do conjunto falhar, o SQLite aborta outras operações e reverte os dados ao seu estado inicial.
Uma transação possui quatro atributos principais, conhecidos como ACID.
- A letra A significa atomicidade. Isso significa que cada transação deve ser tudo ou nada. Se alguma operação na transação falhar, o estado do banco de dados permanece inalterado.
- A letra C significa consistência. Ele garante que qualquer transação trará os dados do banco de dados de um estado válido para outro.
- A letra I significa isolamento. Isso é para controle de simultaneidade. Ele garante que todas as execuções simultâneas de transações produzam o mesmo resultado como se fossem executadas sequencialmente.
- A letra D significa durabilidade. Isso significa que quando a transação for confirmada, ela permanecerá intacta, independentemente de quaisquer erros, como perda de energia.
Exemplo de transação Java SQLite
Quando você se conecta a um banco de dados SQLite, o modo padrão é confirmação automática. Isso significa que cada consulta emitida ao banco de dados SQLite é automaticamente confirmada.
Para desabilitar o modo de confirmação automática, você usa o setAutoCommit()
método do Connection
objeto da seguinte forma:
conn.setAutoCommit(false);
Linguagem de código: Java ( java )
Para confirmar o trabalho, você usa o método commit do Connection
objeto.
conn.commit();
Linguagem de código: Java ( java )
Caso ocorra uma falha no meio da transação, você sempre pode usar o rollback()
método para reverter a transação.
conn.rollback();
Linguagem de código: Java ( java )
O programa a seguir adiciona novo material à tabela de materiais e também lança o estoque. Colocamos ambas as operações na mesma transação.
package net.sqlitetutorial;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
*
* @author tutorials.acervolima.com
*/
public class TransactionApp {
/**
* Connect to the test.db database
*
* @return the Connection object
*/
private Connection connect() {
// SQLite connection string
String url = "jdbc:sqlite:C://sqlite/db/test.db";
Connection conn = null;
try {
conn = DriverManager.getConnection(url);
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return conn;
}
/**
* Create a new material and add initial quantity to the warehouse
*
* @param material
* @param warehouseId
* @param qty
*/
public void addInventory(String material, int warehouseId, double qty) {
// SQL for creating a new material
String sqlMaterial = "INSERT INTO materials(description) VALUES(?)";
// SQL for posting inventory
String sqlInventory = "INSERT INTO inventory(warehouse_id,material_id,qty)"
+ "VALUES(?,?,?)";
ResultSet rs = null;
Connection conn = null;
PreparedStatement pstmt1 = null, pstmt2 = null;
try {
// connect to the database
conn = this.connect();
if(conn == null)
return;
// set auto-commit mode to false
conn.setAutoCommit(false);
// 1. insert a new material
pstmt1 = conn.prepareStatement(sqlMaterial,
Statement.RETURN_GENERATED_KEYS);
pstmt1.setString(1, material);
int rowAffected = pstmt1.executeUpdate();
// get the material id
rs = pstmt1.getGeneratedKeys();
int materialId = 0;
if (rs.next()) {
materialId = rs.getInt(1);
}
if (rowAffected != 1) {
conn.rollback();
}
// 2. insert the inventory
pstmt2 = conn.prepareStatement(sqlInventory);
pstmt2.setInt(1, warehouseId);
pstmt2.setInt(2, materialId);
pstmt2.setDouble(3, qty);
//
pstmt2.executeUpdate();
// commit work
conn.commit();
} catch (SQLException e1) {
try {
if (conn != null) {
conn.rollback();
}
} catch (SQLException e2) {
System.out.println(e2.getMessage());
}
System.out.println(e1.getMessage());
} finally {
try {
if (rs != null) {
rs.close();
}
if (pstmt1 != null) {
pstmt1.close();
}
if (pstmt2 != null) {
pstmt2.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e3) {
System.out.println(e3.getMessage());
}
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
TransactionApp app = new TransactionApp();
app.addInventory("HP Laptop", 3, 100);
}
}
Linguagem de código: Java ( java )
Para verificar o resultado, você pode consultar os dados da materials
tabela and inventory
usando a cláusula inner join da seguinte maneira:
SELECT
name,
description,
qty
FROM
materials
INNER JOIN inventory ON inventory.material_id = materials.id
INNER JOIN warehouses ON warehouses.id = inventory.warehouse_id;
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Neste tutorial, você aprendeu como gerenciar a transação em SQLite usando Java JDBC.