1. pom.xml
디펜던시 추가
1-1 JSON 오브젝트 맵핑을위해 Jackson라이브러리 사용
1-2 Jackson라이브러리가 LocalDateTime클래스를 변환할때 Java 8에서 오류가 발생하기때문에 jsr310 패키지 추가
1-3 기타 DB통신 드라이버 및 Hibernate구현체 및 JPA 라이브러리 디펜던시 추가
--- 생략 ---
<!-- JSON library v2.12.2 -->
<!-- JSON 오브젝트 맵핑 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-version}</version>
</dependency>
<!-- 자바8에서 LocalDateTime클래스를 JSON타입으로 변환하기위해 필요함 -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson-version}</version>
</dependency>
<!-- JDBC template -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.5</version>
</dependency>
<!-- MySQL DB -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.23</version>
</dependency>
<!-- Hibernate Dependencys -->
<!-- 스프링 ORM -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- 스프링 데이터 JPA -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.5.0</version>
</dependency>
<!-- JPA, 하이버네이트 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.4.3.Final</version>
</dependency>
--- 생략 ---
2. appConfig.xml 파일 작성
2-1 Autowired 어노테이션 탐색 위치 지정
2-2 DB접속 커넥션 설정(DataSource)
2-3 JPA 트렌젝션 매니저 설정
2-4 JPA 엔티티 매니저 설정
2-5 Hibernate 기타 상세 설정
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<!-- Repository 패키지 경로 -->
<jpa:repositories base-package="com.server.study.repository" />
<tx:annotation-driven/>
<!-- Autowired 될 객체 패키지 경로 -->
<context:component-scan base-package="com.server.study.service, com.server.study.repository"/>
<!-- DB접속 DataSource 빈생성 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/jpastudy"/>
<property name="username" value="root"/>
<property name="password" value="mariadb"/>
</bean>
<!-- JPA 트랜젝션 매니저 빈생성 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- Hibernate JPA구현 EntityManager 빈생성 -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- Entity 위치 -->
<property name="packagesToScan" value="com.server.study.model"/>
<property name="jpaVendorAdapter">
<!-- 하이버네이트 구현체 사용 -->
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
<!-- 하이버네이트 상세 설정 -->
<property name="jpaProperties">
<props>
<!-- RDB별로 사용하는 SQL문법이 조금씩 다르므로 꼭 알맞게 설정하자 -->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
<!-- SQL 로그-->
<prop key="hibernate.show_sql">true</prop>
<!-- SQL 정렬 -->
<prop key="hibernate.format_sql">true</prop>
<!-- SQL 코멘트 -->
<prop key="hibernate.use_sql_comments">true</prop>
<!-- 새 버전의 ID 생성 옵션 -->
<prop key="hibernate.id.new_generator_mappings">true</prop>
<!-- DDL 자동 생성(프로젝트가 실행 될 떄 Entity로 사용될 테이블을 drop하니 주의하자) -->
<!-- <prop key="hibernate.hbm2ddl.auto">create</prop> -->
</props>
</property>
</bean>
</beans>
3. web.xml
JPA및 프로젝트 설정
3-1 appConfig.xml 파일 경로 설정
--- 생략 ---
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml,/WEB-INF/spring/appServlet/appConfig.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
--- 생략 ---
1. Directory 구조
오류는 신경쓰지 말자(빌어먹을 이클립스)
2. 클래스 구성
2-1 Controller
@RestController
public class HomeController {
@Autowired
MemberService mService;
@PostMapping(path="/insert")
public Member insert(@RequestBody Member member) {
mService.insert(member);
return member;
}
@GetMapping(path = "/select")
public Member select(Member member) {
Member mem = mService.select(member);
return mem;
}
@PatchMapping(path="/update")
public Member update(@RequestBody Member member) {
return mService.update(member);
}
@DeleteMapping(path="delete")
public Boolean delete(@RequestParam Long id) {
return mService.delete(id);
}
}
2-2 Service
select : PK로 데이터를 1개만 조회해 온다.
insert : 객체를 전달하여 테이블에 Insert한다.
update :
1. PK값으로 수정할 데이터를 불러온다.
2. 람다를 통해 데이터를 수정하고 저장한다.( 중요!! )
delete : PK값으로 데이터를 삭제한다.
@Service
public class MemberService {
@Autowired
MemberRepository mRepo;
public Member select(Member member) {
member = mRepo.findById(member.getId()).get();
return member;
}
public void insert(Member member){
mRepo.save(member);
}
public Member update(Member member) {
Optional<Member> db = mRepo.findById(member.getId());
db.ifPresent(selectedMember->{
selectedMember.setName(member.getName());
mRepo.save(selectedMember);
});
return db.get();
}
public Boolean delete(Long id) {
// TODO Auto-generated method stub
try {
mRepo.deleteById(id);
}catch(Exception e) {
return false;
}
return true;
}
}
3. Repository
JPA에서는 @Repository어노테이션을 사용하지 않는다.
그리고 JpaRepository클래스를 상속받는다.
상속받으며 해당 Repository(저장소 or 테이블)과 영속성을 관리할 객체(Model)와 PK를 제네릭타입으로 지정한다.
public interface MemberRepository extends JpaRepository<Member, Long>{
}
4. Model
- 샘플코드에서는 코드를 단축하기위해 롬복을 사용하였다.
- @Entity어노테이션을 통해 영속성을 관리해야하는 객체인것을 선언한다.
- @Table어노테이션을 통해 DB에 어떤 테이블과 매핑되야할지 설정한다.
- Insert쿼리가 실행 될때, 컬럼이 auto_increment되는 것을 @GeneratedValue어노테이션을 통해 설정한다.
- strategy=GenetationType.IDENTITY 를 설정하여 데이터가 유니크한 데이터인것을 알린다.
- @CreationTimeStamp 어노테이션을 통해 default로 현재시간을 입력한다.
- @JsonFormat(pattern="yyyy-MM-dd kk:mm:ss")어노테이션을 통해 JSON으로 변환했을때 표현방식을 설정한다.
- @JsonDeserialize(using = LocalDateTimeDeserializer.class)어노테이션을 통해 LocalDateTime객체를 JSon으로 변환할때 오류가 나지않게 직렬화한다.
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Table(name="member")
public class Member {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY, generator="CUST_SEQ")
private Long id;
private String name;
private String email;
@CreationTimestamp
@JsonFormat(pattern = "yyyy-MM-dd kk:mm:ss")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime create_date;
}
정리하고 보니 설정이 복잡하지 않다.
JPA는 RDB의 데이터를 객체로 다루는 방식이다.
경험을 해보니 단순 조회에서는 혁신적이라고 느껴질 정도로 심플했지만
JOIN이나 복합 검색조건을 구현할 생각을하면 아찔하다...
차근차근 해 나가다 보면 답이 보이겠지...
[jUnit 5] Spring legacy 통합 테스트 (0) | 2021.05.22 |
---|---|
[Hibernate] Spring 5 - JPA - find메소드를 추가하려고할때 주의할점 (0) | 2021.05.13 |
Spring-Boot(Gradle) jar배포 (0) | 2021.04.21 |
Spring - JsonObjectMapper - null제외 (0) | 2021.04.08 |
Spring5 - @RestController에서 쿠키 (0) | 2021.04.08 |
댓글 영역