Database Design

이전에 μ„€κ³„ν•œ API Design 을 기반으둜 κ°„λ‹¨ν•˜κ²Œ Database 섀계 및 sample data λ₯Ό μΆ”κ°€ν•΄λ³΄μž.

CREATE DATABASE  IF NOT EXISTS `employee_directory`;
USE `employee_directory`;
 
--
-- Table structure for table `employee`
--
 
DROP TABLE IF EXISTS `employee`;
 
CREATE TABLE `employee` (
  `id` int NOT NULL AUTO_INCREMENT,
  `first_name` varchar(45) DEFAULT NULL,
  `last_name` varchar(45) DEFAULT NULL,
  `email` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
 
--
-- Data for table `employee`
--
 
INSERT INTO `employee` VALUES 
	(1,'Leslie','Andrews','leslie@luv2code.com'),
	(2,'Emma','Baumgarten','emma@luv2code.com'),
	(3,'Avani','Gupta','avani@luv2code.com'),
	(4,'Yuri','Petrov','yuri@luv2code.com'),
	(5,'Juan','Vega','juan@luv2code.com');
Create Project

Dependency λ₯Ό μœ„μ™€ 같이 ν¬ν•¨μ‹œν‚¨ λ’€, project λ₯Ό generate ν•˜μž.

Development Process

Development Process λŠ” μš°μ„  λ‹€μŒ 단계λ₯Ό λ”°λΌμ„œ μ§„ν–‰ν•œλ‹€.

  1. Update DB configs in application.properties
  2. Create Employee entity (entity class)
  3. Create DAO interface
  4. Create DAO implementation
  5. Create REST controller to use DAO

μ²˜μŒμ—λŠ” μ•„λž˜μ™€ 같은 Architecture 둜 κ΅¬μ„±λœλ‹€.

이전에 DAO λ₯Ό 처음 λ‹€λ€˜μ„ λ•Œμ™€ 같이, DAO λ₯Ό Controller μ—μ„œ 직접 injection λ°›μ•„μ„œ μ‚¬μš©ν•˜λŠ” ꡬ쑰이닀. 이제 Development Process 에 μžˆλŠ” 단계듀을 ν•˜λ‚˜μ”© κ΅¬ν˜„ν•΄λ³΄μž.

μš°μ„  Database configuration 을 λ‹€μŒκ³Ό 같이 application.properties 에 update ν•œλ‹€.

# JDBC properties
spring.datasource.url=jdbc:mysql://localhost:3306/employee_directory  
spring.datasource.username=username  
spring.datasource.password=password

그리고 Database Design ν•œ 것을 기반으둜 Entity Class λ₯Ό μž‘μ„±ν•œλ‹€. Employee.java 에 λ‹€μŒκ³Ό 같이 μž‘μ„±ν•œλ‹€.

@Entity  
@Table(name="employee")  
public class Employee {  
  
    // define fields  
    @Id  
    @GeneratedValue(strategy = GenerationType.IDENTITY)  
    @Column(name="id")  
    private int id;  
  
    @Column(name="first_name")  
    private String firstName;  
  
    @Column(name="last_name")  
    private String lastName;  
  
    @Column(name="email")  
    private String email;
 
	// define constructors
	...
	// define getter/setter
	...
	// define toString
	...
}

μ΄λ ‡κ²Œ @Entity λ₯Ό μ‚¬μš©ν•˜μ—¬ JPA κ°€ μ•Œμ•„μ„œ μ‹€μ œ DB 의 employee table 및 각 field 와 mapping 을 μˆ˜ν–‰ν•˜λ„λ‘ ν•˜λ©΄ entity class 섀정은 끝났닀. μ΄μ œλŠ” DAO λ₯Ό μœ„ν•œ Interface 와 그에 λŒ€ν•œ Implementation 을 λ§Œλ“€μž.

μ΄μ―€μ—μ„œ λ‹€μ‹œ Boss κ°€ μš”μ²­ν•œ API Requirements λ₯Ό ν™•μΈν•΄λ³΄μž.

Create a RET API for the Employee Directory

REST clients should be able to

  • get a list of employees
  • get a single employee by id
  • add a new employee
  • update an employee
  • delete an employee

requirements 의 첫 번째 사항뢀터 ν•˜λ‚˜μ”© κ΅¬ν˜„ν•˜λŠ” μ‹μœΌλ‘œ μ§„ν–‰ν•˜λ©΄ 쒋을 것 κ°™λ‹€. λ‹€μ‹œ DAO 둜 λŒμ•„μ™€μ„œ, λͺ¨λ“  employee 의 list λ₯Ό return ν•  수 μžˆλŠ” method λΆ€ν„° declare ν•˜κ³ , define ν•˜λ©΄ 될 것 κ°™λ‹€.

EmployeeDAO.java interface μ—λŠ” λ‹€μŒκ³Ό 같이 μž‘μ„±ν•˜κ³ ,

public interface EmployeeDAO {   
    List<Employee> findAll();  
}

이λ₯Ό implement ν•˜λŠ” EmployeeDAOImpl.java μ—λŠ” λ‹€μŒκ³Ό 같이 μž‘μ„±ν•˜λ©΄ 될 것이닀.

@Repository  
public class EmployeeDAOImpl implements EmployeeDAO {  
  
    // define field for entity manager  
    private EntityManager entityManager;  
  
    // set up constructor injection  
    public EmployeeDAOImpl(EntityManager entityManager) {  
        this.entityManager = entityManager;  
    }  
  
    @Override  
    public List<Employee> findAll() {  
  
        // create a query  
        TypedQuery<Employee> theQuery = entityManager.createQuery("from Employee", Employee.class);  
  
        return theQuery.getResultList();  
    }  
}

λ§ˆμ§€λ§‰μœΌλ‘œ, ν•΄λ‹Ή DAO λ₯Ό Injection λ°›μ•„ μ‚¬μš©ν•˜λŠ” REST Controller λ₯Ό μž‘μ„±ν•˜λ©΄ requirement ν•˜λ‚˜μ˜ Development Process κ°€ 끝이 λ‚œλ‹€. EmployeeRestController.java μ—λŠ” λ‹€μŒκ³Ό 같이 μž‘μ„±ν•œλ‹€.

@RestController  
@RequestMapping("/api")  
public class EmployeeRestController {  
  
    private EmployeeDAO employeeDAO;  
  
    // quick and dirty: inject employee dao using constructor injection  
    public EmployeeRestController(EmployeeDAO employeeDAO) {  
        this.employeeDAO = employeeDAO;  
    }  
  
    // expose "/employees" and return a list of employees  
    @GetMapping("/employees")  
    public List<Employee> findAll() {  
        return employeeDAO.findAll();  
    }  
}
Potential Problem

κ·ΈλŸ¬λ‚˜ 잠재적인 문제점이 λ³΄μ΄λŠ” 것 κ°™λ‹€. λ§Œμ•½μ— Buiness logic 이 쑰금 더 λ³΅μž‘ν•΄μ Έμ„œ ν•˜λ‚˜μ˜ method 에 μ—¬λŸ¬κ°œμ˜ DAO κ°€ μ‚¬μš©λ˜κ³ , logic 이 λ³΅μž‘ν•΄μ§€λ©΄ Controller λ‚΄λΆ€μ˜ code κ°€ λ¬΄ν•œνžˆ λŠ˜μ–΄λ‚˜ μœ μ§€λ³΄μˆ˜μ— 어렀움이 생길 것이닀.

κ·Έλ ‡λ‹€λ©΄ Controller 와 Buisness logic 을 λΆ„λ¦¬μ‹œν‚¬ ν•„μš”κ°€ μžˆμ„ 것 κ°™λ‹€.