이제 Student 라는 이름의 DAO 를 하나 생성해보자. 순서는 다음과 같다.
- DAO Interface 를 define
- DAO Implement 을 define (+inject entity manager)
- main app 을 update
Step 1: Define DAO Interface
import com.lucvs.cruddemo.entity.Student;
public interface StudentDAO {
void save(Student theStudent);
}위와 같이 Interface 형태로 StudentDAO 를 define 하고, save method 를 declare 한다. save method 는 Implementation 에서 overriding 을 통해 implement 하여 사용하면 될 것이다.
Step 2: Define DAO Implementation
public class StudentDAOImpl implements StudentDAO {
private EntityManager entityManager;
@Autowired
public StudentDAOImpl(EntityManager theEntityManager) {
entityManager = theEntityManager;
}
@Override
@Transactional
public void save(Student theStudent) {
entityManager.persist(theStudent);
}
}Constructor 부분에서, JPA Entity Manager 에서 언급한대로 Spring Boot 가 Entity Manager 를 자동으로 생성해주기 떄문에 @Autowired 를 통하여 EntityManager 를 injection 해주면 된다.
그리고 StudentDAO Interface 에서 declare 한 save method 를 overriding 하여 implement 한다. inject 받은 EntityManger 를 persist method 를 통하여 Student object 를 database 에 저장한다.
@Transactional annotation 은 method 나 class 에 Transaction 을 적용할 수 있도록 해준다.
Transaction
Transaction 은 Database 작업을 하나의 logic 단위로 묶어, 모든 작업이 성공적으로 완료되거나 실패 시 모두 취소되도록 보장하는 기술이다.
Specialized Annotation for DAOs

Spring 은 @Repository 라는 annotation 을 제공한다. @Repository annotation 은 @Component 의 특수화된 형태로, component-scanning 을 통하여 DAO Implementation 을 Bean 의 형태로 자동 등록한다.
또한Database 작업 중 발생하는 다양한 기술 종속적인 JDBC Exception(ex. SQLException, HibernateException 등)들을 Spring이 제공하는 DataAccessException 계열의 Exception 으로 변환해준다.
@Repository
public class StudentDAOImpl implements StudentDAO {
...
}위와 같이 DAO Implementation class 에 대하여 @Repository annotation 을 사용해주면 된다.
Step 3. Update Main Application
@SpringBootApplication
public class CruddemoApplication {
public static void main(String[] args) {
SpringApplication.run(CruddemoApplication.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(StudentDAO studentDAO) {
return runner -> {
createStudent(studentDAO);
}
}
private void createStudent(StudentDAO studentDAO) {
// create the student object
...
// save the student object
...
// display id of the saved student
...
}
}그리고 마지막으로, StudentDAO 를 Main Application 에 Inject 하여 Database 와 Interacting 할 수 있다.
Student DAO - Test (singular saving)
private void createStudent(StudentDAO studentDAO) {
// create the student object
System.out.println("Creating new student object ...");
Student tempStudent = new Student("Arne", "Slot", "arne@liverpool.com");
// save the student object
System.out.println("Saving the student ...");
studentDAO.save(tempStudent);
// display id of the saved student
System.out.println("Saved a student. Generated id: " + tempStudent.getId());
}createStudent method 도 위와 같이 작성한 이후에 Application 을 실행하여 tempStudent object 에 대한 data 가 Database 에 잘 저장되었을지 테스트해보자.

Application 을 실행하면 console 화면에 위와 같이 code 의 실행 상에서는 문제가 없는 것으로 나왔다. 그럼 실제 Database 에 theStudent obejct 가 잘 저장되었는지 확인해보자.
SELECT * FROM student_tracker.student;위와 같이 SELECT 를 이용하여 query 를 날려주면 이전에 만들어놓은 student table 을 조회할 수 있다.

성공적으로 Database 에 직접 생성한 theStudent object 의 data 가 저장된 것을 볼 수 있다.
결과에서 볼 수 있듯이, theStudent object 를 만들 때 Contructor 의 argument 에 id 값을 넣어서 initialize 해주지 않았음에도 불구하고 1 이라는 값이 들어가 있다.
이로써 이전에 Student Entity Class 를 만들 때 id field 에 대하여 지정한 ID Generation Strategy 역시도 정상적으로 동작한 것을 알 수 있다.
Student DAO - Test (multiple saving)
이번에는 여러 개의 Student object 를 생성하여 Database 에 저장한 이후, PK(Primary Key) 로 설정한 id column 에 값들이 잘 저장되는지 확인해보자.
id에 대하여GenerationType.IDENTITYstrategy 를 사용했기 때문에, DB 내부에서는AUTO_INCREMENT` 로 동작한다.
추가적으로, MySQL Workbench 에서 특정 table 을 우클릭하면 위와 같은 메뉴가 나오는데, 여기서 Alter Table
Changing Index of MySQL Auto Increment
기본적으로 Auto-Increment 를 사용하게 되면 index 가 1 부터 시작되는 것을 확인할 수 있었다. 그러나 다음 SQL query 를 통하여 시작 index 를 원하는 숫자로 바꿀 수 있다.
ALTER TABLE student_tracker.student AUTO_INCREMENT=1000
이후에 Application 을 실행하면 위와 같이 PK 의 시작 index 가 ALTER query 를 통하여 설정한 1000 부터 시작하는 것을 알 수 있다.
TRUNCATE student_tracker.student참고로 위와 같이 TRUNCATE query 를 실행하면 해당 table 의 모든 row 를 삭제한다. primary key 역시 시작 index 로 다시 초기화된다.