✅ 자바 어플리케이션에서 관계형 데이터베이스를 다루기 위한 자바 영속성 프레임워크로 persistence 계층이다.
JPA(Java Persistence API)는 [[ORM]]을 위해 Java에서 지원하는 표준 API다 (인터페이스, 추상클래스의 집함)
퍼시스턴스계층? 데이터를 쥐고 있고, 불필요한 DB커넥션을 줄일 수 있음. 이를 통해 비용을 줄이고, 메모리제이션
JPA, [[JDBC]] 둘 다 데이터베이스와 상호 작용하는 데 사용되는 두 가지 다른 기술이지만 그 차이는 Persistence(영속성)에 있다.
[!info] JPA & JDBC & Hibernate
JDBC: 직접 SQL 쿼리를 작성하여 데이터베이스와 통신, 개발자가 연결, 처리 모두 관리
JPA: 객체 지향 프로그래밍과 관계형 데이터베이스 간의 매핑을 제공하여, 개발자는 객체를 사용하여 데이터 관리(SQL 쿼리를 직접 작성하지 않아도 됩니다.)
[[Hibernate]](ORM F/W): 쿼리문이 없어 사용이 용이하지만 제어권이 없어 자유도는 줄어듦.
Persistence(영속성) : 어플리케이션 종료 후에도 객체가 유지된다
대용량 데이터베이스 솔루션이 없는 기업, 복잡한 수식이 필요없는 곳에서 주로 쓰임
최근 NoSQL이 부각되고 있음 - 쿼리 메소드 select(), where() 등 / 네이티브 Query
저장소가 달라도 일관된 데이터 처리 가능
JPA를 위한 저장소(JpaRepository) 관련기능 제공
Repository <- CrudRepository <- PagingAndSortingRepository(페이징처리, 정렬지원) <-JpaRepository
EntityManager : Entity 저장관리, 사용자마다 하나씩 사용(공유x) 1:1
EntityManagerFactory : EntityManager 생성
=> 이 클래스를 통해 사용자는 직접 SQL문을 작성하여 DB에 명령을 내리지 않고, EntityManager로 작업
저장 pertitst(Member) => 두 번 호출해도 한 번만 저장이 되어서 무결성 제약조건을 지킬 수 있음!!
조회 find() => findAll(), findByWriter() => findByXXX(Id/Title/Writer)
변경 Entity setter
삭제 remove()
반영 transaction=tx
- tx.begin() snapshot만
- tx.commit() 이제 반영됨
1.JPQL : DB테이블이 아닌 엔티티를 대상으로 쿼리를 작성 => 네이티브 SQL문으로 변경한다.
- 에러 찾기 어려움 - 디버깅, 트러블 슈팅 등 => QUerydsl 생성
2.쿼리메소드(주로 사용) : 메소드 이름으로 JPQL 자동 생성(단, 간단한 쿼리문에 유리)
- Spring Data 참조(https://docs.spring.io/spring-data/jpa/reference/repositories/query-keywords-reference.html)
- 예 : `List bList = boardRepository.findByTitleAndWriter("제목1","작성자1");
3.JAP Criterial : JPQL을 메소드의 조합으로 작성 - JPA 표준, 직관적으로 매우 불편함
- 예 : cq.select(b).where(cb.equals(b.get("title")"title"));
4.Querydsl : JPQL을 메소드의 조합으로 작성 - 라이브러리 오픈소스
- 예 : `List bList = queryFactory.selectForm(board).where(board.title.eq("title)).fetch();
5.NativeSQL ; JPQL 대신 SQL 직접 작성(@Query 사용 가능) -> 이럴거면 그냥 MyBatis로 하지
JPQL & SQL
DB에 독립적 / DB에 의존적이다.
조회대상 엔티티 / DB테이블
대소문자 구분 / 비구분
@Table 오늘날짜로 변경(Member, Board)
JPA는 데이터가 영속성을 갖는다고 했었다면, 만약 데이터가 삭제되는 메소드를 실행하면??
EntityManager em이 제공하는 메소드 (CRUD)
JPA에서 데이터가 삭제된다는 것은 영속성을 갖고 있던 데이터가 비영속성으로 전환되면서 상태가 변경된다는 것!
public void boardDelete(int b_No) {
Board board = boardRepository.findById(b_No).orElse(null);
if(board != null){
boardRepository.deleteById(b_No); //영속성이 비영속성으로 전환되는 순간
}
}
Quill은?
✅ 웹 기반의 리치 텍스트 편집기입니다. 사용자가 웹 애플리케이션에서 텍스트를 편집할 수 있도록 다양한 기능과 도구를 제공
텍스트 편집 기능을 구현하고, 사용자에게 편리하고 다양한 텍스트 편집 환경을 제공
hidden - 화면에는 보이지 않지만 백엔드 처리를 위해 가져와야할 때 설정함
과정 : 사진첨부 클릭 시 요청 -> 사진 표시(비동기처리 With ajax) & 이미지에 태그가 붙어서 넣어짐(우리가 설정한 것 : image)
세세한 코드작성보다는 어떤 흐름으로 이루어지고, 그 과정에서의 처리는 동기인지, 비동기인지 아는 것 필요함
방식 : Post, data : formData 로 처리
과정 : 사진첨부 클릭 시 요청 -> 사진 표시(비동기처리 With ajax) & 이미지에 태그가 붙어서 넣어짐(우리가 설정한 것 : image)
주의 : pds 뒤에 / 는 Mac, 윈도우는 \ 역슬래쉬로 나오니 확인바람.
servlet:
multipart:
max-file-size: 10MB #one file size
max-request-size: 50MB #multi file size
package com.example.demo;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties
@ConfigurationProperties
@Data
public class YAMLConfig {
private String uploadPath;
}
@RestController
@RequestMapping("/board/*")
public class RestBoardController {
Logger logger = LoggerFactory.getLogger(RestBoardController.class);
@Autowired
private YAMLConfig config;
@PostMapping("imageUpload")
public String imageUpload(@RequestParam(value = "image")MultipartFile image)throws Exception{ //톰캣에게 미루기!!
logger.info("RestBoardController-imageUpload");
File upImage = new File(config.getUploadPath(), image.getOriginalFilename());
image.transferTo(upImage);//단, 파일이름 반환 필요
return image.getOriginalFilename(); //사용자가 선택한 파일 이름 반환됨
}