start.spring.io 에서 시작
'Developer' 카테고리의 다른 글
[JPA실전]devtools dependency (0) | 2020.09.28 |
---|---|
[JPA실전]lombok 다운 (0) | 2020.09.28 |
[JPA]벌크연산 (0) | 2020.09.23 |
[JPA]JPQL-Named쿼리 (0) | 2020.09.22 |
[JPA]쿼리에 Entity 직접 사용하기 (0) | 2020.09.22 |
start.spring.io 에서 시작
[JPA실전]devtools dependency (0) | 2020.09.28 |
---|---|
[JPA실전]lombok 다운 (0) | 2020.09.28 |
[JPA]벌크연산 (0) | 2020.09.23 |
[JPA]JPQL-Named쿼리 (0) | 2020.09.22 |
[JPA]쿼리에 Entity 직접 사용하기 (0) | 2020.09.22 |
니 운동 좀 했는갑네.
몸이 벌크업됐노.
에서 벌크란 통? 이라고 할수가 있다. 통, 즉, 사이즈가 업됐노.
이렇게 생각할수 있는데.
벌크연산도 통연산 이라고 해석해도 될거같다.
통으로 연산 때리는 거다.
쿼리 한번으로 여러 테이블 로우 조져버리는거임.
update와 delete를 지원한다.
뭐 JPA 표준 스펙에는 없는데 하이버네이트가 지원하는것도 있다.
inset into ...select ~~ 이런거.
select해서 insert 조지는거...뭐 이런정도?
int resultCount = em.createQuery("update Member m set m.age=100").executeUpdate();
System.out.println("resultCount = " + resultCount);
em.createQuery에 update문 쌔리고 .executeUpdate 때리면 된다.
결과값은 변경된 컬럼수가 나옴.
========================================================================
벌크 연산은 영속성 컨텍스트를 무시해버리고 DB에 직접 쿼리 때린다.
잘못하면 망한다. 어떻게 하느냐?
-벌크 연산 먼저 실행 (flush 자동으로 됨)
-벌크 연산 수행 후 영속성 컨텍스트를 초기화
하면 된다.
아래경우 나이가 모두 100으로 바뀌지 않고 출력이 된다.
왜냐면 자동 flush insert 다 때리고 clear를 안해줬으니 영속성 컨텍스트에는 값들이 남아있기 때문에.
Team team = new Team();
team.setName("teamA");
em.persist(team);
Team team1 = new Team();
team1.setName("teamB");
em.persist(team1);
Member member = new Member();
member.setUsername("userA");
member.setAge(10);
member.setType(MemberType.ADMIN);
Member member1 = new Member();
member1.setUsername("userB");
member1.setAge(70);
member1.setType(MemberType.USER);
Member member2 = new Member();
member2.setUsername("userC");
member2.setAge(90);
member2.setType(MemberType.USER);
member.setTeam(team);
member1.setTeam(team1);
member2.setTeam(team1);
em.persist(member);
em.persist(member1);
em.persist(member2);
//flush 자동 호출
int resultCount = em.createQuery("update Member m set m.age=100").executeUpdate();
System.out.println("resultCount = " + resultCount);
System.out.println("member1.getAge() = " + member.getAge());
System.out.println("member1.getAge() = " + member1.getAge());
System.out.println("member1.getAge() = " + member2.getAge());
System.out.println(" ======================================================= ");
tx.commit(); //이시점에 DB 쿼리가 날라감
그럼 이때는?
~
~
~
em.persist(member);
em.persist(member1);
em.persist(member2);
//flush 자동 호출
int resultCount = em.createQuery("update Member m set m.age=100").executeUpdate();
System.out.println("resultCount = " + resultCount);
Member mem = em.find(Member.class, member.getId());
System.out.println("mem = " + mem.getAge());
System.out.println(" ======================================================= ");
tx.commit(); //이시점에 DB 쿼리가 날라감
ㅋㅋ 이때도 mem.getAge 해봤자 100이 안나옴..
왜냐하면 벌크연산은 DB로 바로 쿼리를 쳐때려버리고 영속성 컨텍스트를 개무시하니까.
즉, 영속성 컨텍스트에 남아있는 em.persist(member); 이 놈을 불러옴.ㅋ....미띤
그래서 clear를 여기 써주면 새로가져온다
int resultCount = em.createQuery("update Member m set m.age=100").executeUpdate();
System.out.println("resultCount = " + resultCount);
em.clear();
Member mem = em.find(Member.class, member.getId());
[JPA실전]lombok 다운 (0) | 2020.09.28 |
---|---|
[JPA실전]시작 (0) | 2020.09.28 |
[JPA]JPQL-Named쿼리 (0) | 2020.09.22 |
[JPA]쿼리에 Entity 직접 사용하기 (0) | 2020.09.22 |
[JPA]다형성 JPQL 쿼리 (0) | 2020.09.22 |
어마어마한 메리트가 있다.
Named 쿼리란 미리 정의해서 이름을 부여해두고 사용하는 JPQL이다.
정적쿼리..변하지않음..(메리트있음)
어노테이션이나 xml에 정의 가능하다.
진짜장점 : 애플리케이션 로딩시점에 초기 화 후 재사용, 애플리케이션 로딩시점에 쿼리 검증 가능!!
도랐맨. 무슨말.
직접해보자.
Entity
@NamedQuery(name = "Member.findByUsername", query = "select m from Member m where m.username = :username")
public class Member {
@Id
@GeneratedValue
private Long id;
private String username;
private int age;
~
~
~
이렇게 선언해줌
사용은 이렇게.
List<Member> resultList = em.createNamedQuery("Member.findByUsername", Member.class).setParameter("username", "userC")
.getResultList();
for (Member mem : resultList) {
System.out.println("mem = " + mem);
}
그럼 기대값대로 나온다.
신기한것은 애플 실행할때
Named 쿼리에 오타가 있으면 에러발생시킴.
@NamedQuery(name = "Member.findByUsername", query = "selectt m from Member m where m.username = :username")
select를 selectt로 바꾸고 하니 에러가 뜬다.
어노테이션에 등록 되어있기 때문에 미리 파싱해서 sql로 들고있으려고 하는데 문법에 안맞네.ㅋ 오류내야지 이거임
대부분의 오류를 다 잡아준다.
그렇다고 네임드 쿼리 몇백줄씩 하면 안되겠지?
============================================================
그리고 xml에 정의할 수도 있다.
xml이 항상 우선권을 가진다.
애플리케이션 운영 환경에 따라 다른 xml을 배포할 수 있다.
뭐 근데...엔티티가 더러워지니까 좀 별로긴해
[JPA실전]시작 (0) | 2020.09.28 |
---|---|
[JPA]벌크연산 (0) | 2020.09.23 |
[JPA]쿼리에 Entity 직접 사용하기 (0) | 2020.09.22 |
[JPA]다형성 JPQL 쿼리 (0) | 2020.09.22 |
[JPA]BatchSize - 전역선언해서 사용하기 (0) | 2020.09.22 |
select count(m) from member m
과 select count(m.id) from member m 은 같다.
똑같이 select count(m.id) from member m 으로 sql을 박는다.
그리고 파라미터로 엔티티 자체를 줄수도 있다.
select m from member m where m=:member
쿼리를 이렇게 짜고 .setParameter("member", member)
로 파라미터를 주면 이것 은 곧
select m from member m where m.id=:memberId
와 같다.
JPA 엔티티는 DB에 넘어갈때 PK로 넘어가게 된다.
당연하지만 흥미롭다.
[JPA]벌크연산 (0) | 2020.09.23 |
---|---|
[JPA]JPQL-Named쿼리 (0) | 2020.09.22 |
[JPA]다형성 JPQL 쿼리 (0) | 2020.09.22 |
[JPA]BatchSize - 전역선언해서 사용하기 (0) | 2020.09.22 |
[JPA]BatchSize - LAZY로딩 시 몇개를 가져올거냐? (0) | 2020.09.22 |
타입을 지정해서 뽑을수 있다.
다운캐스팅 같이 위처럼 사용도 할수 있다.
[JPA]JPQL-Named쿼리 (0) | 2020.09.22 |
---|---|
[JPA]쿼리에 Entity 직접 사용하기 (0) | 2020.09.22 |
[JPA]BatchSize - 전역선언해서 사용하기 (0) | 2020.09.22 |
[JPA]BatchSize - LAZY로딩 시 몇개를 가져올거냐? (0) | 2020.09.22 |
[JAP]fetch 조인 - 특징과 한계 (0) | 2020.09.22 |
쿼리가 N+1이 아니라 딱 테이블 수만큼 맞출수가 있다.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="hello">
<properties>
<!-- 필수 속성 -->
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test"/>
<property name="hibernate.dialect" value="dialect.MyH2Dialect"/>
<!-- 옵션 -->
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.use_sql_comments" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="create" />
<property name="hibernate.default_batch_fetch_size" value="100"/>
</properties>
</persistence-unit>
</persistence>
[JPA]쿼리에 Entity 직접 사용하기 (0) | 2020.09.22 |
---|---|
[JPA]다형성 JPQL 쿼리 (0) | 2020.09.22 |
[JPA]BatchSize - LAZY로딩 시 몇개를 가져올거냐? (0) | 2020.09.22 |
[JAP]fetch 조인 - 특징과 한계 (0) | 2020.09.22 |
[JPA]JPQL - distinct 중복제거 (0) | 2020.09.22 |
참 골때리는 놈이다.
String query = "select t from Team t";
List<Team> resultList = em.createQuery(query, Team.class).
setFirstResult(0).setMaxResults(2).getResultList();
System.out.println("resultList = " + resultList.size());
for (Team t : resultList) {
System.out.println("t.getName()+\"|\"+t.getMembers().size()+\"명\" = " + t.getName()+"|"+t.getMembers().size()+"명");
for (Member m : t.getMembers()) {
System.out.println("m = " + m);
}
}
아래는 Team의 Member 리스트 선언.
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
만약 이대로 실행하면 맨처음 Team 가져오는 select 쿼리때리고 지연로딩이니까 프록시 가져온 다음,
루프 안에서 팀 개수대로 Member select 쿼리를 조질것이다.
그럼 결국 총 2번의 member select 쿼리를 조지지.
근데 이 조짐의 대상의 수를 조절할수가 있다.ㅋㅋ
방법은 BatchSize를 쓰는것이다.
@BatchSize(size = 2)
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
이렇게 한번에 몇개를 조질지 사이즈를 정하면 한방에 몇개를 가져오느냐를 정할수 있다.
사이즈를 2로 했으니 2번 할 작업을 한번만 할거다.
실행하면 루프안에서 select 한번만 때린다.
사이즈를 1로 하면 어차피 없는거나 다름없으므로 역시 2번을 때린다.
[JPA]다형성 JPQL 쿼리 (0) | 2020.09.22 |
---|---|
[JPA]BatchSize - 전역선언해서 사용하기 (0) | 2020.09.22 |
[JAP]fetch 조인 - 특징과 한계 (0) | 2020.09.22 |
[JPA]JPQL - distinct 중복제거 (0) | 2020.09.22 |
[JAP]fetch 조인 - 한방쿼리 (0) | 2020.09.22 |
연관된 엔티티들을 SQL 한번으로 조회 - 성능 최적화
LAZY 전략보다 우선시 되어 한방에 DB에서 뽑아온다.
실무에서는 글로벌 로딩 전략은 모두 지연로딩(LAZY 로딩) 으로 잡고,
최적화가 필요한 곳에 이 fetch 조인은 적용한다. (성능 문제 대부분 해결)
fetch 조인 대상에게는 별명을 줄수 없다.
근데 하이버네이트는 가능하긴 한데 사용하지 말자.
어차피 다 조회하는 한방쿼리인데 그 대상의 속성들에게 별명을 줄 필요도 없고 준다해도 위험함.
그리고 둘 이상의 컨렉션은 fetch 조인을 할수 없다.
컬렉션을 fetch 조인 하면 페이징을 사용할수가 없다.
일대일, 다대일 같은 단일 값 연관 필드들은 fetch 써도 페이징 가능.
데이타가 뻥튀기 되기 때문에 컬렉션을 fetch 조인하면 페이징을 절대 못함.
일대다 를 뒤집어서 다대일로 바꿔서 페이징 구현할 수도 있음.
작동은 해도 개판되는거임. 망함. (하이버네이트는 경고로그를 남기고 메모리에서 페이징함,겁나위험함)
[JPA]BatchSize - 전역선언해서 사용하기 (0) | 2020.09.22 |
---|---|
[JPA]BatchSize - LAZY로딩 시 몇개를 가져올거냐? (0) | 2020.09.22 |
[JPA]JPQL - distinct 중복제거 (0) | 2020.09.22 |
[JAP]fetch 조인 - 한방쿼리 (0) | 2020.09.22 |
[JPA]JPQL 기본 함수 (0) | 2020.09.21 |