diff --git a/.gitignore b/.gitignore index 2f43530..ee9c430 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,130 @@ buildNumber.properties .project # JDT-specific (Eclipse Java Development Tools) .classpath +### Java template +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +### Maven template +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +# Eclipse m2e generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +.idea/* +*.iml + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..8675a73 --- /dev/null +++ b/pom.xml @@ -0,0 +1,88 @@ + + + 4.0.0 + + jpa-basic + ex1-hello-jpa + 1.0-SNAPSHOT + + + + 17 + + UTF-8 + UTF-8 + + + 5.5.7.Final + + 2.2.220 + 2.0.6 + 1.4.7 + + + + + org.hibernate + hibernate-entitymanager + ${hibernate.version} + + + + com.h2database + h2 + ${h2db.version} + + + org.projectlombok + lombok + 1.18.28 + provided + + + + org.slf4j + slf4j-api + ${slf4j-version} + + + org.slf4j + jcl-over-slf4j + ${slf4j-version} + runtime + + + org.slf4j + slf4j-log4j12 + ${slf4j-version} + runtime + + + ch.qos.logback + logback-classic + ${logback.version} + + + org.jetbrains + annotations + RELEASE + compile + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + + + + + \ No newline at end of file diff --git a/src/main/java/hellojpa/Jpa2.java b/src/main/java/hellojpa/Jpa2.java new file mode 100644 index 0000000..4898227 --- /dev/null +++ b/src/main/java/hellojpa/Jpa2.java @@ -0,0 +1,85 @@ +package hellojpa; + + +import hellojpa.model.Member; +import lombok.extern.slf4j.Slf4j; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.Persistence; +import java.util.List; + +@Slf4j +public class Jpa2 { + public Jpa2(EntityManagerFactory emf) { + EntityManager em = emf.createEntityManager(); + EntityTransaction tx = em.getTransaction(); + tx.begin(); + try{ + // 추가 +// insertMember(em, tx); + // 조회 +// selectMember(em); + // 수정 +// updateMember(em, tx); + + // 삭제 +// deleteMember(em, tx); + + // JPQL + jpql(em); + + +// tx.commit(); + } catch (Exception e){ + tx.rollback(); + } finally { + em.close(); + } + emf.close(); + } + + // JPQL + private void jpql(EntityManager em) { + List result = em.createQuery("select m from Member as m", Member.class) + .setFirstResult(5) + .setMaxResults(8) + .getResultList(); + + for (Member member : result) { + System.out.println("member.name = " + member.getName()); + } + } + + // 추가 + private static void insertMember(EntityManager em, EntityTransaction tx) { + Member member = new Member(); + member.setId(1L); + member.setName("HelloA"); + em.persist(member); + tx.commit(); + } + + // 조회 + private static void selectMember(EntityManager em) { + Member findMember = em.find(Member.class, 1L); + } + + // 수정 + private static void updateMember(EntityManager em, EntityTransaction tx) { + Member findMember = em.find(Member.class, 1L); + findMember.setName("HelloJPA"); + tx.commit(); + } + + // 삭제 + private static void deleteMember(EntityManager em, EntityTransaction tx) { + // 엔티티 조회, 영속 상태 + Member memberA = em.find(Member.class, "memberA"); + em.remove(memberA); + tx.commit(); + } + + +} diff --git a/src/main/java/hellojpa/Jpa3.java b/src/main/java/hellojpa/Jpa3.java new file mode 100644 index 0000000..9c08f8a --- /dev/null +++ b/src/main/java/hellojpa/Jpa3.java @@ -0,0 +1,200 @@ +package hellojpa; + + +import hellojpa.model.Member1; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import java.util.List; + +public class Jpa3 { + public Jpa3(EntityManagerFactory emf) { + EntityManager em = emf.createEntityManager(); + EntityTransaction tx = em.getTransaction(); + tx.begin(); + try{ + // 엔티티 조회 +// persistSelectMember(em); + // 엔티티 등록 +// persistinsertMember(em, tx); + // 엔티티 삭제 +// deleteMember(em); + // flush +// fulsh(em); + // 준영속 +// detach(em, tx); +// detachedClear(em); +// detachedClose(em, tx); + + // 비영속 병합 +// TransientMerge(em, tx); + + + } catch (Exception e){ + tx.rollback(); + } finally { + em.close(); + } + // 병합 +// detachedMerge(emf); + emf.close(); + } + + private void TransientMerge(EntityManager em, EntityTransaction tx) { + Member1 member = new Member1(); + Member1 newMember = em.merge(member); // 비영속 병합 + tx.commit(); + } + + // 엔티티 조회 + private void persistSelectMember(EntityManager em) { + Member1 member = new Member1(); + member.setId("member1"); + member.setUserName("회원1"); + + // 1차 캐시에 저장됨 + em.persist(member); + + // 1차 캐시에서 조회 + Member1 findMember = em.find(Member1.class, "member1"); + System.out.println("findMember.id = " + findMember.getId()); + } + + // 엔티티 추가 + private void persistinsertMember(EntityManager em, EntityTransaction tx) { + + Member1 memberA = new Member1(); + memberA.setId("memberA"); + memberA.setUserName("회원1"); + Member1 memberB = new Member1(); + memberB.setId("member2"); + memberB.setUserName("회원2"); + + em.persist(memberA); + em.persist(memberB); + // 여기까지 INSERT SQL을 데이터베이스에 보내지 않는다. + + // 커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다. + tx.commit(); //[트랜잭션] 커밋 + } + + // 엔티티 삭제 + private void deleteMember(EntityManager em) { + Member1 memberA = em.find(Member1.class, "member1"); + em.remove(memberA); + } + + // flush + private void fulsh(EntityManager em) { + Member1 memberA = new Member1(); + memberA.setId("member1"); + memberA.setUserName("회원1"); + + Member1 memberB = new Member1(); + memberB.setId("member2"); + memberB.setUserName("회원2"); + + em.persist(memberA); + em.persist(memberB); + // 중간에 JPQL 실행 시 자동으로 flush 호출 + List query = em.createQuery("select m from member m", Member1.class).getResultList(); + + } + + // 준영속 + private void detachedClose(EntityManager em, EntityTransaction tx) { + Member1 memberA = em.find(Member1.class, "memberA"); + Member1 memberB = em.find(Member1.class, "memberB"); + + tx.commit(); // 트랜잭션 커밋 + + em.close(); // 영속성 컨텍스트 종료 + } + + // 준영속 + private void detachedClear(EntityManager em) { + // 엔티티 조회, 영속 상태 + Member1 member = em.find(Member1.class, "memberA"); + + em.clear(); // 영속성 컨텍스트 초기화 + + // 준영속 상태 + member.setUserName("changeName"); + + } + + // 준영속 + private void detach(EntityManager em, EntityTransaction tx) { + // 회원 엔티티 생성, 비영속 상태 + Member1 member = new Member1(); + member.setId("memberA"); + member.setUserName("회원A"); + + // 회원 엔티티 영속 상태 + em.persist(member); + + // 회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태 + em.detach(member); + tx.commit(); // 트랜잭션 커밋 + } + + // 병합 + private void detachedMerge(EntityManagerFactory emf) { + Member1 member1 = createMember(emf); + member1.setUserName("회원명변경"); + mergeMember(emf, member1); + + } + + // 병합 + private void mergeMember(EntityManagerFactory emf, Member1 member) { + EntityManager em = emf.createEntityManager(); + EntityTransaction tx = em.getTransaction(); + tx.begin(); + try{ +// Member1 mergeMember = em.merge(member); + member = em.merge(member); // 준영속 엔티티를 참조하던 변수를 영속 엔티티를 참조하도록 변경하는것이 안전하다 + tx.commit(); + // 준영속 상태 + System.out.println("member = " + member.getUserName()); + + // 영속 상태 +// System.out.println("mergeMember = " + mergeMember.getUserName()); + System.out.println("em contains(member) = " + em.contains(member)); +// System.out.println("em.contains(mergeMember) = " + em.contains(mergeMember)); + // 결과 + // member = 회원명변경 + // mergeMember = 회원명변경 + // em contains(member) = false + // em.contains(mergeMember) = true + } catch (Exception e){ + tx.rollback(); + } finally { + em.close(); + } + } + + // 병합 + private Member1 createMember(EntityManagerFactory emf) { + EntityManager em = emf.createEntityManager(); + EntityTransaction tx = em.getTransaction(); + tx.begin(); + Member1 member = new Member1(); + try{ + member.setId("member1"); + member.setUserName("회원3"); + + em.persist(member); + tx.commit(); + + } catch (Exception e){ + tx.rollback(); + } finally { + em.close(); // 영속성 컨텍스트 종료 + // member 엔티티는 준영속 상태 + } + return member; + } + +} diff --git a/src/main/java/hellojpa/JpaMain.java b/src/main/java/hellojpa/JpaMain.java new file mode 100644 index 0000000..39f300d --- /dev/null +++ b/src/main/java/hellojpa/JpaMain.java @@ -0,0 +1,21 @@ +package hellojpa; + +import hellojpa.model.Member; +import lombok.extern.slf4j.Slf4j; + +import javax.persistence.*; +import java.util.List; + +@Slf4j + +public class JpaMain { + public static void main(String[] args) { + log.debug("teste========"); + EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello"); +// Jpa2 jp = new Jpa2(emf); + Jpa3 jp = new Jpa3(emf); + + } + + +} \ No newline at end of file diff --git a/src/main/java/hellojpa/model/Member.java b/src/main/java/hellojpa/model/Member.java new file mode 100644 index 0000000..1aafdfb --- /dev/null +++ b/src/main/java/hellojpa/model/Member.java @@ -0,0 +1,15 @@ +package hellojpa.model; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +@Getter@Setter +public class Member { + @Id + private Long id; + private String name; +} diff --git a/src/main/java/hellojpa/model/Member1.java b/src/main/java/hellojpa/model/Member1.java new file mode 100644 index 0000000..58599f7 --- /dev/null +++ b/src/main/java/hellojpa/model/Member1.java @@ -0,0 +1,15 @@ +package hellojpa.model; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +@Getter@Setter +public class Member1 { + @Id + private String id; + private String userName; +} diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000..f1c2c5a --- /dev/null +++ b/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..e699ab3 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,28 @@ + + + + + + %d{HH:mm:ss} [%-5level] %logger{36}[line: %L] - %msg%n + + + + + /tmp/access.log + + /tmp/access-%d{yyyy-MM-dd}.log + 50 + + + + %d{HH:mm:ss} [%-5level] %logger{36}[line: %L] - %msg%n + + + + + + + + + + \ No newline at end of file