我試圖使用DAO模式插入到具有一對一關係的兩個表中。我有customer
和address
表。每個customer
都有一個address_id
字段,其中引用了address
表的ID。Java DAO模式多表原子事務
我想要做的是插入客戶地址爲address
表,並獲取生成address_id
,並使用該客戶插入customer
表。如果其中任何任務失敗,數據庫保持不變。
我沒有使用像spring或hibernate這樣的框架,只是簡單的JDBC和DAO模式。
這是代碼。在Application.java
,首先我插入地址,然後插入客戶。如果客戶插入失敗,地址將保留在數據庫中。
我可以關閉數據庫連接的自動提交,並將地址和客戶插入合併到一個數據庫連接中,但這是否與DAO模式相對應?
Customer.java:
package com.example.model;
public class Customer {
private long id;
private String firstName;
private String lastName;
private String email;
private byte[] salt;
private byte[] digest;
private Address address;
// getters and setters
}
Address.java:
package com.example.model;
public class Address {
private long id;
private String address;
private String postalCode;
private String phone;
// getters and setters
}
AddressDAO.java:
package com.example.dao;
import com.example.model.Address;
public interface AddressDAO {
void create(Address address);
}
AddressDAOImpl.java:
package com.example.dao;
import com.example.model.Address;
import com.example.util.DatabaseUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class AddressDAOImpl implements AddressDAO {
private static final Logger LOG = LoggerFactory.getLogger(AddressDAOImpl.class);
@Override
public void create(Address address) {
String sql = "INSERT INTO address (address, postal_code, phone) VALUES (?, ?, ?)";
try (PreparedStatement ps = DatabaseUtil.getConnection()
.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS)) {
ps.setString(1, address.getAddress());
ps.setString(2, address.getPostalCode());
ps.setString(3, address.getPhone());
ps.executeUpdate();
try (ResultSet rs = ps.getGeneratedKeys()) {
if (rs.next()) {
address.setId(rs.getShort(1));
}
}
} catch (SQLException e) {
LOG.error(e.getMessage(), e);
}
}
}
CustomerDAO.java:
package com.example.dao;
import com.example.model.Customer;
public interface CustomerDAO {
void create(Customer customer);
}
CustomerDOAImpl.java:
package com.example.dao;
import com.example.model.Customer;
import com.example.util.DatabaseUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class CustomerDAOImpl implements CustomerDAO {
private static final Logger LOG = LoggerFactory.getLogger(CustomerDAOImpl.class);
@Override
public void create(Customer customer) {
String sql = "INSERT INTO customer (first_name, last_name, email, address_id, salt, digest) " +
"VALUES (?, ?, ?, ?, ?, ?)";
try (PreparedStatement ps = DatabaseUtil.getConnection()
.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS)){
ps.setString(1, customer.getFirstName());
ps.setString(2, customer.getLastName());
ps.setString(3, customer.getEmail());
ps.setLong(4, customer.getAddress().getId());
ps.setBytes(5, customer.getSalt());
ps.setBytes(6, customer.getDigest());
ps.executeUpdate();
try (ResultSet rs = ps.getGeneratedKeys()) {
if (rs.next()) {
customer.setId(rs.getLong(1));
}
}
} catch (SQLException e) {
LOG.error(e.getMessage(), e);
}
}
}
Application.java:
package com.example;
import com.example.dao.AddressDAO;
import com.example.dao.AddressDAOImpl;
import com.example.dao.CustomerDAO;
import com.example.dao.CustomerDAOImpl;
import com.example.model.Address;
import com.example.model.Customer;
public class Application {
public static void main(String[] args) {
Customer customer = new Customer();
Address address = new Address();
CustomerDAO customerDAO = new CustomerDAOImpl();
AddressDAO addressDAO = new AddressDAOImpl();
address.setAddress("Address");
address.setPostalCode("123456789");
address.setPhone("987654321");
customer.setFirstName("John");
customer.setLastName("Doe");
customer.setEmail("[email protected]");
customer.setAddress(address);
addressDAO.create(customer.getAddress());
customerDAO.create(customer);
System.out.println(customer.getId());
}
}
如果你想要東西以原子方式執行,那麼你需要使用事務,如果那個_「與DAO模式相對應」_是一個意見問題。模式是指導,而不是法律。 –