Spring (2)
JPA
1. Entity
**테이블 생성 시 실행은 잠시 멈췄다가 테이블 다 만들고 실행시켜보자 아님 문제 생김 진짜 중요함**
dto 느낌임
근데 DB에서 테이블을 만들지 않고도 테이블 생성 가능함
먼저,
속성에서 해줘야할 게 있음
/*application.properties*/
spring.jpa.hibernate.ddl-auto=update
속성에서 update라고 해줄 경우에 내가 쓰는 DB에 테이블 생성됨
spring.jpa.hibernate.ddl-auto=validate
validate는 테이블 생성 후 정상 매핑되었는지 확인함
테이블 생성 후 계속 validate로 유지
- Entity에서 필요한 어노테이션
@Data
@Entity
@Table(name = "테이블명")
@SequenceGenerator(name = "시퀀스명", sequenceName = "DB에 저장될 시퀀스명",
initialValue = 초기값, allocationSize = 증가값) //꼭 쓰는건 아님
@Entity는 해당 클래스를 테이블로 인식할 수 있도록 만드는 어노테이션
@Table(name = "테이블명")은 생성하고자하는 테이블, 또는 생성되어 있는 테이블 매칭함
@SequenceGenerator는 시퀀스 지정하고자 할 때 쓰임
- Entity class 내부 어노테이션
@Column을 생략하면 변수명이 컬럼명이 된다
@Column(nullable = false) // not null
@Column(length = 200) // 200 설정
@Column(name = "id") // 컬럼명 직접지정
@ColumnDefault는 default 값 지정하는 건데
@Column(columnDefinition = "long default 1")
직접 썼을 땐 위와 같이 써야 default값이 먹혔다
@ColumnDefault로 하니 default 안됐음 그래서 위의 방식대로 한 것
해당 필드에 @Id 어노테이션을 붙이면 그 필드는 DB테이블의 기본키가 된다
@DateTimeFormat은 자기가 원하는 패턴으로 데이터를 입력 받아올 수 있다
@CreationTimestamp는 데이터가 추가(생성)시에만 날짜 정보 저장된다
@UpdateTimestamp는 데이터 변경시에도 날짜 정보가 변경 된다
@GeneratedValue는 시퀀스 어노테이션임
이걸 쓰기 위해선 @SequenceGenerator가 필요하다
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_B1")
<코드>
@Data
@Entity
@Table(name = "MEMBER1")
public class Member1 {
@Id //기본키
@Column(name = "ID", length = 50)
private String id;
private String pw;
private String name;
private int age;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
@CreationTimestamp
private Date regdate;
}
그러고 코드 실행하면
DB에 테이블이 생성되는걸 볼 수 있는데
이후엔 환경 설정으로 가서 꼭 validate로 바꿔줘야한다
spring.jpa.hibernate.ddl-auto=validate
2. Repository
Repository는 Mapper 느낌이라고 생각하면 될 것 같다
그리고 꼭 interface로 설정 해주자
- Repository에 필요한 어노테이션
@Repository
<코드>
@Repository
public interface Member1Repository extends JpaRepository<Member1, String>{
}
초반 코드는 별게 없다 이게 끝이다
JpaRepository<엔티티명, 엔티티의 기본키 타입> 으로 설정해주면된다.
JpaRepository에는 기본적인 CRUD 구현 되어있기때문에
CRUD를 제외한 나머지는 직접 만들어야 함
그때 필요한 사이트가
https://docs.spring.io/spring-data/jpa/docs/2.7.10/reference/html/#jpa.sample-app.finders.strategies
들어가서 참고하면 된다.
사용방법은 findBy변수명으로 주로 쓰인다고 보면 된다
<예시>
// 전체 조회
// SPQL => select * from member1 order by name desc;
public List<Member1> findAllByOrderByNameDesc();
// 검색
// SPQL => select * from member1 where name like '%?%' order by name desc;
public List<Member1> findByNameContainingOrderByNameDesc(String name);
라고 생각하면 될 것 같다
findAll은 파라미터 필요 없음 전체를 갖고 오는거라서
find만 있을경우 파라미터 필요함
전체를 가지고 오는게 아니라면 List로 해줄 필요는 없다
3. controller
controller는 항상 하던대로 해주면 된다
@Slf4j
@Controller
@RequestMapping(value = "/member1")
@RequiredArgsConstructor
public class Member1Controller {
final String format = "Member1Controller => {}";
final Member1Repository m1Repository; //저장소 객체 ////원래는 Service 써야하는데 생략했음
/* ----------------------------------------------------------------- */
//회원가입
//127.0.0.1:9090/ROOT/member1/join.do
@GetMapping(value = "/join.do")
public String joinGET(){
return "/member1/join"; //templates / member1 / join.html 이동 (화면 나옴)
}
@PostMapping(value="/join.do")
public String joinPOST(@ModelAttribute Member1 member1) {
try {
log.info(format, member1.toString()); //꼭 찍어보자
//저장소 호출해서 DB에 넣기해야함 (mapper, service가 없는데도 들어가짐)
m1Repository.save(member1); //sql문을 안쓰면 DB종류 상관없이 넘어가니깐 이런점에선 좋음
return "redirect:/member1/join.do";
} catch (Exception e) {
e.printStackTrace();
return "redirect:/home.do";
}
}
return "/example/join";
=> 이거는 html로 이동할 때 쓰이고
return "redirect:/home.do";
=> 특정 HTTP응답을 통해 다른 URL로 재요청하라고 지시하는 거?
=> 음 .. 앞의 코드가 전부 실행된 후 이동해야하는 곳을 가르키는? 느낌?? 뭬?