2017-02-17 71 views
1

我试图使用DAO模式插入到具有一对一关系的两个表中。我有customeraddress表。每个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()); 
    } 
} 
+0

如果你想要东西以原子方式执行,那么你需要使用事务,如果那个_“与DAO模式相对应”_是一个意见问题。模式是指导,而不是法律。 –

回答

0

由于这是一比一的关系,并假设你止跌” t本身创建一个地址,我只是把地址创建在CustomerDAOImpl中。稍后,如果有必要,您可以稍后在AddressDAO中公开地址对象的检索。地址的更新也可以通过相同的CustomerDAOImpl类来处理。

如果您将来在过渡到JPA/Hibernate时将从框架展示相同的行为,那么从长远角度来看,这种方法会更好。另外,这样可以防止您在DAO类之间进行自己的事务/连接管理。