[SpringStudy] 3. EntityManager, EntityManagerFatory


Entity


EntityはDB中のテーブルにマッチする概念と考えられる.
たとえば、データベースにid、name、ageをフィールド値として含む
CREATEメンバー表を作成するには、次のQUERYを入力する必要があります.
CREATE TABLE `Member` (
  `id` BIGINT(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`id`)
)
ただし、上記のクエリ文をJPAでJavaコードを生成すると、次のコードと同じになります.
@Entity
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(nullable = false)
    private long id;
    
    @Column(nullable = false)
    private String name;
    
    @Column(nullable = false)
    private int age;
    
    ... Getter, Setter
}
基本的に、JPAはすべてのフィールド(id、name、age)のロードを実現している.
ただし、すべての場合、idフィールドとnameフィールドのみがすべてのフィールドに関連しない場合があります.
@Entity
@Table(name = "Member")
public class MemberOnlyName {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(nullable = false)
    private long id;
    
    @Column(nullable = false)
    private String name;
    
    ... Getter, Setter
}
    
したがって、メンバー・テーブルは1つしかありませんが、場合によっては複数のEntityを作成できます.

EntityManager



Entity Managerは、上記のEntity(CRUD=ストレージ、クエリー、変更、削除)を管理するクラスです.
その名の通り、Entityを格納する仮想DBとすることができます.
DBのみを使用するアプリケーションは、通常、EntityManagerFactoryを1つだけ作成します.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("해당이름");
EntityManager em = emf.createEntityManager();
上記のコードを使用すると、EntityManagerFactoryで必要に応じてEntityManagerを生産できます.
このようにして生成されたEntity Managerは、データベース接続が必要になるまで接続を取得しません.
JPA実装にはHibernateが含まれる.
EntityManagerFactoryを作成すると、プールDB Connectionも作成されます.
これらの情報の設定方法は、1) maven projectまたは2) spring projectに依存する.

1)認定項目の場合

resources - META-INFフォルダの下部にpersistence.xmlファイルを作成してデータベースを設定する必要があります.
<?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="jpa3"> <!-- 프로젝트 이름 -->
      <properties>
          
          <!-- DB와 연결하기 위한 필수 속성 -->
          <!-- MySQL 설정 -->
        <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver" />
		<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/testdb?serverTimezone=UTC"/>
		<property name="javax.persistence.jdbc.user" value="root"/>
		<property name="javax.persistence.jdbc.password" value="1234"/>
        
        <!-- DB Dialect(방언) 설정(MySQL) -->
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />

        <!-- 옵션(선택) 속성 -->
        <!-- hiberante의 실행 과정에서 콘솔에 테이블 생성, DDL, DML 등 SQL문을 출력하도록 -->
        <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"/>

      </properties>
  </persistence-unit>
</persistence>
[注意]
  • <persistence-unit name="jpa3">nameはプロジェクト名と同じでなければなりません!
  • <property name="hibernate.hbm2ddl.auto" value="create"/>TABLEをCREATEに変換した後、updateに変更する必要があります!
    :createを使用して既存のテーブルDROPを作成し、CREATEの新しいテーブルを作成します.
  • 2)Springプロジェクトの場合

    resourcesは、下部のapplication.propertiesファイルにDBを設定する必要があります.(MySQLを使用)

    [注意]
  • spring.datasource.url=jdbc:mysql://localhost:3306/testdb?serverTimezone=UTCはtestdbに設定されています.
    生成された新しいTABLEはtestdbDBに格納される.

  • サーバを一度実行した後、createを
  • spring.jpa.hibernate.ddl-auto=createに変更する必要があります.そうしないと、既存のTABLEはDROPされません.
    : create = DROP + CREATE
  • 持続性コンテキスト


    Entity Managerは、内部の永続性コンテキストでエンティティを管理します.

    永続性コンテキスト=エンティティを永続的に保存する環境.
    しかし、開発者は永続性コンテキストの内部を直接分解したり表示したりすることはできません.そのため、いくつかの論理的または抽象的な概念と見なす必要があります.
    EntityManagerを使用してエンティティを保存または参照します.
    エンティティマネージャは、永続性コンテキストでエンティティを保持および管理します.

    EntityMangerとPersistence Contextはどのようにエンティティを管理しますか?

    public class Join {
    
        public void join(String name, int age) {
            // 아직까지는 해당 엔티티를 엔티티 매니저가 관리하지 않는다.
            Member member = new Member();
            member.setName(name);
            member.setAge(age);
            
            EntityManagerFactory emf = Persistence.createEntityManagerFactory("해당폴더명");
    		EntityManager em = emf.createEntityManager();
            EntityTransaction tx = em.getTransaction();
            
            try {
                // 엔티티 매니저에서 수행하는 모든 로직은 트랜잭션 안에서 수행돼야 한다.
                tx.begin();
                
                // 이렇게 하면 해당 엔티티 매니저의 영속성 컨텍스트에 위에서 만든 member 객체가 저장된다.  
                // 이제 member 엔티티는 엔티티 매니저의 관리 대상이 되고, 영속성을 가졌다고 말할 수 있다.
                em.persist(member);
                
                // 영속성 컨텍스트에 있던 모든 SQL쿼리가 실행된다.
                // Commit하지 않으면 DB에 data가 저장되지 않는다.
                tx.commit();
            } catch(Exception e) {
                // 어떤 이유에서 오류가 났다면 트랜잭션을 롤백 시켜줘야한다.
                tx.rollback();
            } finally {
                // 엔티티 매니저 종료
                em.close();
            }
        }
    }
    なぜこれを書いたのかはわかりませんが一目見ればよかったです

    EntityManagerFatory


    複数のスレッドが同時にアクセスされると、Entity Managerで同時性の問題が発生するため、スレッド間で共有することはできません.
    他のスレッドでデータを事前に変更できないため、データを修正しています.
    したがって、Entity Managerは1つを共有することはできません.状況に応じて作成を続行する必要があります.
    このEntityManagerを作成したのがEntityManagerFactoryです.
    public class Join {
        public void join(String name, int age) {
            // 아직까지는 해당 엔티티를 엔티티 매니저가 관리하지 않는다.
            Member member = new Member();
            member.setName(name);
            member.setAge(age);
            
            // META-INF/persistence.xml에서 이름이 db인 persistence-unit을 찾아서 엔티티 매니저 팩토리를 생성 
            EntityManagerFatory emf = Persistence.createEntityManagerFactory("db");
            EntityManager em = emf.createEntityManager();
            EntityTransaction tx = em.getTransaction();
            
            try {
                // 엔티티 매니저에서 수행하는 모든 로직은 트랜잭선 안에서 수행돼야 한다.
                tx.begin();
                
                // 이렇게 하면 해당 엔티티 매니저의 영속성 컨텍스트에 위에서 만든 member 객체가 저장된다.  
                // 이제 member 엔티티는 엔티티 매니저의 관리 대상이 되고, 영속성을 가졌다고 말할 수 있다.
                em.persist(member);
                
                // 트랜잭션을 커밋한다.
                tx.commit();
            } catch(Exception e) {
                // 어떤 이유에서 오류가 났다면 트랜잭션을 롤백 시켜줘야한다.
                tx.rollback();
            } finally {
                // 엔티티 매니저 종료
                em.close();
            }
            emf.close(); // 마찬가지로 엔티티 매니저 팩토리도 종료
        }
    }
    工場から製品を印刷する概念と考えられる.
    エンティティーマネージャとは異なり、エンティティーマネージャリポジトリは複数のスレッドに同時にアクセスできます.
    費用的には、工場を建てる費用が大きいようですが、
    各DBにはEntityManagerFatoryが1つしか使用されません.
    出典:https://perfectacle.github.io/2018/01/14/jpa-entity-manager-factory/
    https://sweets1327.tistory.com/60
    https://velog.io/@jaeseok-go/JPA-%EC%98%81%EC%86%8D%EC%84%B1