JPA
- 스프링에서 데이터 처리를 돕는 라이브러리
- DB에 종속적인 SQL문 없이도 개발이 가능하기 때문에 개발의 생산성을 제고
- 기존의 JDBC 등을 이용해 직접 구현했던 DB 관련 작업을 대신 처리해주는 추상화된 계층의 구현 스펙
Ready Settings
- pom.xml의 <dependencies>내에 필요한 기능의 태그 삽입 (mysql, tomcat-embed-jasper, jstl, jaxb-runtime, jaxb-api 등)
server.port=9002
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springdb?serverTimezone=Asia/Seoul
spring.datasource.username=rheemingyu
spring.datasource.password=a1234
spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
spring.jpa.database=mysql
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.mvc.view.prefix=/WEB-INF/mycar/
spring.mvc.view.suffix=.jsp
spring.devtools.livereload.enabled=true
- src/main/resources>application.properties
- 사용하는 프로젝트의 기본 설정 세팅
- hibernate.ddl-auto : 스키마 생성 시 동일한 이름의 테이블 삭제 후 생성(create), 변경 부분만 반영(update)
- update 설정 시 기존에 존재하던 컬럼명과 동일한 컬럼명을 만들 시 기존 데이터 보존, 새로운 컬럼은 null 삽입
Entity
- JPA에서는 엔티티는, 테이블에 대응하는 하나의 클래스와 유사한 개념
- JPA에서 '하나의 엔티티 타입을 생성한다'라는 의미는 '하나의 클래스를' 작성한다는 의미
- spring-boot-starter-data-jpa 의존성을 추가하고 @Entiy 어노테이션을 붙이면, 테이블과 java 클래스가 매핑
Spring Boot Settings
@SpringBootApplication
@ComponentScan({"mycar.data"})
@EntityScan("mycar.data")
@EnableJpaRepositories("mycar.data")
public class SpringBootJpaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootJpaApplication.class, args);
}
}
- src/main/java>(Root Package)>~Application.java
- @SpringBootApplication : 이 어노테이션을 위 파일의 클래스에 등록하면 해당 어플리케이션이 Spring Boot 기반에서 작동하도록 설정됨
- @ComponentScan : Beans에 등록을 위한 세팅을 스캔하기 위한 범위의 패키지 등록
- @EntityScan : 엔티티를 자동 생성할 클래스의 범위의 패키지 등록
- @EnableJpaRepositories : sql문 작성 없이도 일반적 DB 작동을 지원하는 객체 제공의 범위를 받고자 하는 패키지 등록
DTO_Entity
@Entity
@Table(name = "mycar")
@Data
public class MyCarDto {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long num;
@Column(name = "carname")
private String carname;
@Column
private int carprice;
@Column
private String carcolor;
@Column
private String carguip;
@CreationTimestamp
@Column(updatable = false)
private Timestamp guipday;
}
- @Entity : 해당 클래스를 엔티티 클래스로 등록
- @Table : 엔티티 클래스의 데이터를 이용하여 DB에 테이블을 생성
- @Data : getter, setter, toString의 기능 대체
- @Id : 해당 변수를 각 엔티티를 구별하는 식별자 아이디로 지정 (SQL의 기본 키 개념)
- @GeneratedValue : 해당 변수를 엔티티로 만들 테이블의 기본키로 등록
- strategy=GenerationType.AUTO : 기본키 데이터가 자동 생성되며, 입력 시 null 값을 입력해야 함
- @Column : 해당 변수를 테이블의 컬럼으로 등록
- name : 등록될 컬럼명 지정, 미지정 시 변수명 그대로 등록
- @CreationTimeStamp : Timestamp 변수에 사용하며, 엔티티 생성 시 해당 시점의 시간을 자동으로 입력
- updatable=false : 테이블 update 시 해당 컬럼의 데이터는 불변 (JPA에서는 sql문을 자의로 변경할 수 없으므로, 이 조건이 없는데 update 데이터를 미입력 시 null 값으로 인식)
DAO
public interface MyCarDaoInter extends JpaRepository<MyCarDto, Long>{
}
- JpaRepository : JPA에 등록된 sql문을 제공하는 인터페이스 (제네릭 : Key-엔티티 등록 클래스명, Value-Id(기본키) 변수의 자료형)
- 따라서 JpaRepository를 상속한 인터페이스는 JPA에 등록된 모든 sql문에 해당하는 추상 메서드를 포함 (이를 implements 시 모두 override해야 함)
@Repository
public class MyCarDao {
@Autowired
MyCarDaoInter carInter;
public void insertMyCar(MyCarDto dto) {
carInter.save(dto);
}
public List<MyCarDto> getAllData() {
return carInter.findAll();
}
public MyCarDto getData(long num) {
return carInter.getReferenceById(num);
}
public void updateMyCar(MyCarDto dto) {
carInter.save(dto);
}
public void deleteMyCar(long num) {
carInter.deleteById(num);
}
}
- 기존 Spring Framework에서는 Repository 클래스에서 인터페이스를 직접 상속(implements)했지만, JPA 사용 시 현실적으로 불가능
- JPA를 사용하기 위해서는 JpaRepository 인터페이스를 상속해야 하는데, 해당 인터페이스는 매우 많은 sql문을 구현한 추상 메서드를 포함하므로 이를 상속 시 모든 메서드를 override 해야하므로 능률 저하
- 따라서 JpaRepository를 상속한 인터페이스를 생성(Autowired)하여 필요한 메서드 객체를 호출하여 사용
- 기본적 sql문을 구현한 메서드
- save(DTO) : insert와 update 공용 (파라미터 클래스에, @Id로 등록된 변수(기본키)의 데이터가 null 값이면 insert로 동작, null이 아니면 update로 동작)
- findAll() : select * from ENTITY;
- getReferenceById(Id) : select * from ENTITY where SEQ=Id;
- deleteById(Id) : delete from ENTITY where SEQ=Id;
Controller & View
- 기존의 Spring Framework와 사용법 동일 (DAO의 메서드 호출하여 사용)