이제 Student λΌλŠ” μ΄λ¦„μ˜ DAO λ₯Ό ν•˜λ‚˜ μƒμ„±ν•΄λ³΄μž. μˆœμ„œλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

  1. DAO Interface λ₯Ό define
  2. DAO Implement 을 define (+inject entity manager)
  3. 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 둜 λ‹€μ‹œ μ΄ˆκΈ°ν™”λœλ‹€.