2017-02-17 4 views
1

Я пытаюсь использовать шаблон DAO для вставки в две таблицы, которые имеют отношения «один-к-одному». У меня есть customer и address столов. Каждый customer имеет поле address_id, которое ссылается на идентификатор таблицы address.Java DAO pattern multiple table atomic transaction

Что я хочу сделать, это вставить адрес клиента в таблицу address и получить сгенерированный address_id и использовать его для вставки клиента в таблицу customer. Если какая-либо из этих задач не удалась, база данных осталась без изменений.

Я не использую никаких фреймворков, таких как весна или спящий режим, просто 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

Поскольку это соотношение один к одному, и если вы Wouldn» t создать адрес сам по себе, я просто поставил бы создание адреса в CustomerDAOImpl. Позже вы могли бы выявить поиск объектов Address в AddressDAO позже, если это необходимо. Обновления адреса также могут обрабатываться через тот же класс CustomerDAOImpl.

Этот подход будет работать лучше в долгосрочной перспективе, если вы должны перейти в JPA/Hibernate в будущем, когда такое же поведение будет проявляться в рамках. Кроме того, это не дает вам возможности сделать свое собственное управление транзакциями/подключением между классами DAO.