Java DAO模式多表原子事务
我试图使用DAO模式插入到两个具有一对一关系的表中。我有Java DAO模式多表原子事务,java,database,jdbc,dao,Java,Database,Jdbc,Dao,我试图使用DAO模式插入到两个具有一对一关系的表中。我有客户和地址表格。每个customer都有一个address\u id字段,该字段引用address表的id 我要做的是将客户地址插入地址表,并获取生成的地址\u id,然后使用该id将客户插入客户表。如果其中任何一项任务失败,数据库将保持不变 我没有使用spring或hibernate之类的框架,只是使用带有DAO模式的普通JDBC 这是代码。在Application.java中,首先插入地址,然后插入客户。如果客户插入失败,则地址仍保留在
客户
和地址
表格。每个customer
都有一个address\u id
字段,该字段引用address
表的id
我要做的是将客户地址插入地址
表,并获取生成的地址\u id
,然后使用该id将客户插入客户
表。如果其中任何一项任务失败,数据库将保持不变
我没有使用spring或hibernate之类的框架,只是使用带有DAO模式的普通JDBC
这是代码。在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);
}
}
}
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);
}
}
}
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.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);
}
}
}
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("john.doe@mail.com");
customer.setAddress(address);
addressDAO.create(customer.getAddress());
customerDAO.create(customer);
System.out.println(customer.getId());
}
}
由于这是一种一对一的关系,并且假设您不会自己创建地址,我只会将地址的创建放在CustomerDAOImpl中。以后,如果有必要,您可以在AddressDAO中公开地址对象的检索。对地址的更新也可以通过相同的CustomerDAOImpl类处理
从长远来看,如果将来要过渡到JPA/Hibernate,框架将显示相同的行为,那么这种方法将工作得更好。此外,这还可以避免您必须在DAO类之间进行自己的事务/连接管理。如果您希望事务以原子方式执行,那么您需要使用事务,如果“与DAO模式相对应”是一个意见问题的话。模式是指导,而不是法律。