2017-02-17 66 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類之間進行自己的事務/連接管理。