커리큘럼(12-30/변경)
01. Java
02. git
03. Database
04. Jsp [Server]
05. HTML,CSS
07. JS
06. 미니프로젝트-2W
08. SpringFramework , SrpingBoot (v)
09. React JS [Front-end]
10. 중간프로젝트 (1M)
11. Linux 명령어
12. AWS 클라우드
13. DevOps - Docker
14. App - Android
15. 최종프로젝트 (1M)
스프링 부트
JPA(Java Persistence API)
- ORM(Object - Relation Mapping)
- DB데이터 - <맵핑> - 필드를 연결하는 것
- 구현 클래스와 RDB(Relational DataBase)에서 쓰이는 데이터인 테이블을 매핑(연결)하는 것을 의미
JPA란
- SQL작성없이 SQL문을 실행시키는 API
- 자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스
- 인터페이스 모음으로 개발자가 JPA를 사용하면, JPA 내부에서 JDBC API를 사용하여 SQL을 호출하여 DB와 통신
- 실제로는
하이버네이트
가 동작
하이버네이트(Hibernate)
- JPA의 구현체 중 하나
- Hibernate가 지원하는 메서드 내부에서는 JDBC API가 동작하고 있으며, 단지 개발자가 직접 SQL을 직접 작성하지 않음
동작흐름
엔티티(Entity)
: 데이터베이스 테이블과 매핑되는 자바 클래스로 각 엔티티 인스턴스는 테이블의 행을 나타냄
영속성 컨텍스트(Persistence Context)
: 엔티티 객체를 관리하고 데이터베이스와의 동기화를 담당하는 환경으로 EntityManager
가 이를 관리
- 엔티티를 기억하는 1차 캐시역할
(데이터를 조회하는 기능을 처리할 때, DB에서 바로 조회하는 것이 아니라 영속성 컨텍스트에서 먼저 조회)
엔티티 매니저(Entity Manager)
: JPA의 핵심 인터페이스로, 엔티티의 CRUD작업을 관리
- Spring Boot의 경우 Bean에 EntityManager가 자동으로 등록되어있어서 @persistenceContext어노테이션으로 사용할 수 있음
엔티티 매니저 팩토리(Entity Manager Factory)
: EntityManager
인스턴스를 생성하며 애플리케이션 전역에서 하나의 EntityManagerFactory
만 생성하는 것이 일반적
- 요약
- JPA호출(insert)
- EntityManager Factory는 EntityManager를 생성
- 영속성 컨텍스트에 Entity를 영구등록
- EntityManager는 영속성 컨텍스트를 기반으로 CRUD작업 수행
스프링부트 JPA
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
# JPA의존성이 추가되면 DB연결 선언은 필수가 됩니다.
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring?serverTimezone=Asia/Seoul
spring.datasource.username=계정
spring.datasource.password=비밀번호
@Entity//JPA가 관리함
@Table(name = "MEMO")//테이블명
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class Memo {
@Id //pk
@GeneratedValue(strategy = GenerationType.IDENTITY)//auto_increament를 대신함
//시퀀스에 대한 전략
// @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "my_seq")
// @SequenceGenerator(name = "my_seq", sequenceName = "my_sequence", allocationSize = 1)
private long mno;
@Column(nullable = false, length = 100)
private String writer;
@Column(columnDefinition = "varchar(200) default 'y'")
private String text;
}
//<엔티티명, 엔티티의ID타입>
public interface MemoRepository extends JpaRepository<Memo, Long> {
//생략...
CRUD구문
JPA 문법 |
표현식 |
insert작업 |
save(엔티티객체) |
select작업 |
findById(키타입), findAll, getOne(키타입) |
update작업 |
save(엔티티객체) |
delete작업 |
deleteById(키타입), delete(엔티티객체) |
@Test
public void testCode01(){
for(int i=2;i<=300;i++) {
Memo memo = Memo.builder().writer("admin" + i).text("sample" + i).build();
memoRepository.save(memo);
}
}
// select 함수 - find키워드
@Test
public void testCode02(){
Optional<Memo> memo = memoRepository.findById(1L);
if(memo.isPresent()){ // 값이 있다면
Memo m = memo.get(); // 값을 꺼냄
System.out.println(m.toString());
}
}
// select함수
@Test
public void testCode03(){
List<Memo> memo = memoRepository.findAll();
System.out.println(memo.toString());
}
// update함수
@Test
public void testCode04(){
Memo memo = Memo.builder().mno(1L).writer("test").text("test").build();
Memo result = memoRepository.save(memo);
if(result ==null){
System.out.println("업데이트 실패");
}
else{
System.out.println("업데이트 성공: "+result.toString());
}
}
//delete- delete, deleteById
@Test
public void testCode05(){
memoRepository.deleteById(1L);
}
정렬
@Test
public void testCode01(){
// Sort sort = Sort.by("text").descending(); // 컬럼명
Sort sort = Sort.by("text").descending()
.and(Sort.by( "mno").descending());
List<Memo> list = memoRepository.findAll(sort);
System.out.println(list.toString());
}
페이지 처리
@Test
public void testCode02(){
Pageable pageable = PageRequest.of(0,20); // 1번 페이지 20개의 데이터
Page<Memo> page = memoRepository.findAll(pageable);
for(Memo m : page.getContent()){
System.out.println(m.toString());
}
System.out.println("전체페이지수: "+page.getTotalPages());
System.out.println("전체 데이터수 : " +page.getTotalElements());
System.out.println("현재 조회하고 있는 페이지 번호 : "+ page.getNumber());
System.out.println("amount값 : "+page.getSize());
System.out.println("데이터의 존재여부: "+page.hasContent());
System.out.println("이전 페이지 여부 :"+page.hasPrevious());
System.out.println("다음 페이지 여부 :"+page.hasNext());
System.out.println("시작페이지 여부:"+page.isFirst());
System.out.println("마지막페이지 여부:"+page.isLast());
}
쿼리메서드
# DAO 인터페이스
//쿼리 메서드 - 메서드의 유형을 보고 JPA가 select문을 실행
// where mno between ? and ?
List<Memo> findByMnoBetween(Long start,Long end);
// where text=? order by mno desc
List<Memo> findByTextOrderByMnoDesc(String text);
// where writer in (?,?,?) order by mno asc
List<Memo> findByWriterIsInOrderByMnoAsc(List<String> list);
// where mno between ? and ? order by mno desc
List<Memo> findByMnoBetweenOrderByMnoDesc(Long start,Long end);
// where text like ? or writer like ? order by mno desc
List<Memo> findByTextContainingOrWriterContainingOrderByMnoDesc(String text, String writer);
@Autowired
private MemoRepository memoRepository;
@Test
public void test01(){
List<Memo> list = memoRepository.findByMnoBetween(10L,20L);
System.out.println(list.toString());
}
@Test
public void test02(){
List<Memo> list = memoRepository.findByTextOrderByMnoDesc("sample5");
System.out.println(list.toString());
}
@Test
public void test03(){
List<String> find = Arrays.asList("admin3","admin85","admin107");
List<Memo> list = memoRepository.findByWriterIsInOrderByMnoAsc(find);
System.out.println(list.toString());
}
@Test
public void test04(){
List<Memo> list = memoRepository.findByMnoBetweenOrderByMnoDesc(10L,20L);
System.out.println(list.toString());
}
@Test
public void test05(){
List<Memo> list = memoRepository.findByTextContainingOrWriterContainingOrderByMnoDesc("sample5","admin1");
System.out.println(list.toString());
}