学習(2)-3章永久性管理~4章シンボルマッピング


インフラストラクチャ-金英漢の
Java ORM標準JPAプログラミングコースの学習を参考にします.
https://www.inflearn.com/course/ORM-JPA-Basic/dashboard

持続性コンテキスト

  • エンティティを永続的に格納環境
  • 非可視論理概念
  • エンティティーマネージャを使用して、永続性コンテキストにアクセスします.
  • EntityManager.persist(entity)
    エンティティをDBに格納するのではなく、永続性コンテキストと呼ばれる場所に格納します.

    エンティティのライフサイクル

      Member member = new Member();
      member.setId(2L);
      member.setName("HelloB");
  • 非零速
    =>永続コンテキストに依存しない
  •   Member member = new Member();
      member.setId(2L);
      member.setName("HelloB");
      em.persist(member) // 영속성 컨텍스트에 엔티티를 저장한다.
  • 英領
    =>持続性コンテキストで管理するステータス
  •   Member member = new Member();
      member.setId(2L);
      member.setName("HelloB");
      em.persist(member)
      em.detach(member) // 지우기
  • 準零速
    =>持続性コンテキストに格納後、分離状態
  • になる.
    em.remove(member);
    削除
  • プライマリキャッシュ



    永続性コンテキストには、プライマリキャッシュと呼ばれるコンテンツがあります.(@Id, Entity)
    Mapのように身長と価値がある感じ
    クエリー時に、セカンダリコンテキストでプライマリキャッシュを検索します.データベースを検索するのではありません.
    プライマリ・キャッシュに存在しないオブジェクトは、プライマリ・キャッシュに存在するかどうかを確認し、データベースをクエリーし、データベースからインポートしてプライマリ・キャッシュに保存します.
    その後クエリーしても、永続性コンテキストがクエリーされます.
          Member member = new Member();
          member.setId(2L);
          member.setName("HelloB");
                
          System.out.println("==before==");
          em.persist(member);
          System.out.println("==after==");
          Member findMember = em.find(Member.class, 1L); // DB에 접근하지않기떄문에 셀렉쿼리 안뜬다. 
          System.out.println("findMember.id =" + findMember.getId());
          System.out.println("findMember.name= " + findMember.getName());
          tx.commit();
    findはdbから取り出すのではなく、上に格納されているプライマリキャッシュでクエリーを行います.
    Insertクエリーのみが表示され、selectクエリーは表示されません.
    ビジネスが非常に複雑な場合、クエリーは減少する可能性がありますが、ビジネスにはあまり役に立ちません.
    コンセプトメリット(オブジェクト向けコード)は、パフォーマンスのメリットよりも大きくなります.
    いずれにしてもリクエストごとにDBトランザクションが1つしか管理されていないので、リクエストが終了すると削除されますか?

    永続エンティティの一貫性の確保


    同一性=同じインスタンスであることを保証します.
    同等性=インスタンスは異なる場合がありますが、同じ値を保証します.
    Member member1 = em.find(Member.class, 2L);
    Member member2 = em.find(Member.class, 2L);
    System.out.println(member1==member2); // true
    オブジェクト内の同一性とリレーショナル・データベース内の同一性の例の不一致を解決する利点
    ただし、javaは、オブジェクト識別(a=b)とオブジェクト同一性(a.equals(b))を同時に定義します.

    疑問点SpringbootのMybatisコンシステンシ保証?





    複数のブログ記事では、JPAは同一性を保証していますが、MybatisやJDBCを使用する場合に同一性を保証できない場合、Mybatisは同一性を保証できませんか?テストをして、保障がありました.
    Spring FrameworkがブートではなくMybatisを使っているからだと思います
    私はスティーブンたちと話した.
    1.異なるデータベース内の異なるトランザクションの独立性レベル
    ある話です現在のMysql環境でテストしたことがありますが、Mysqlの独立性レベルはREEATABLE READです(トランザクション内でデータのクエリを繰り返しても、結果は同じです).
    独立性レベルを2つのレベルを意図的に下げるREAD UNCOMMITTED(トランザクション内にコミットされていないデータにアクセス可能)に変更し、テストを行います.

    でも、結局そうだった.
    2.Mybatis自身のキャッシュ機能
    Mybatisはローカルキャッシュ機能をデフォルトとして使用し、localCacheScopeのポーリング値はSESSION
    SESSIONにはSqlSessionがあり、同じSQLを繰り返し呼び出したときにキャッシュされた同じ結果が得られます.
    トランザクションが完了またはコミットまたはロールバックされたり、挿入、更新、削除が実行されたりすると、キャッシュの生存範囲は破棄されます.
    (それが原因らしい)
    STATEMENTは、同じSqlSessionであっても、SQLクエリごとにキャッシュされます.

    localCacheScopeをSTATEMENTとします.

    これこそ同一性を保証することはできない.

    同じinsert文を解放すると、Mybatisに異常が発生します.
    Mybatisにはキャッシュの概念が存在するため、クエリはキャッシュの結果を受け取るため、一貫性が保証されます.
    ただし、データの挿入、修正、削除にはJPAのような書き込みバッファの概念は存在しないため、同じオブジェクトでも2回のクエリ文が実行されます.
    私が思いついた結論(JPAが一貫性を保証する物語について)

  • JPAは、テーブルとオブジェクトの同一性のパターンを一致させることができる.
    =>テーブルの概念は、プライマリ・キー、オブジェクト定義が等しい(equals()、)と等しい(=、実際のインスタンスが同じかどうか).

  • Mybatisはクエリー時に同一性を保証しますが、挿入、削除、変更時に同一性を保証することはできません.Insert、update、deleteを実行すると、ローカルキャッシュのキャッシュが破棄されるためです.
  • 来週、学習者ともう一度話をしてから追加する予定です.

    トランザクションの書き込み遅延をサポート

    em.persist(memberA) // 이순간 JPA가 엔티티를 1차캐시에 넣어두고 분석하여 sql을 생성하고, 쓰기지연 sql저장소라는곳에 생성해둔다
    em.persist(memberB) // memberB도 1차캐시에 넣어놓고 쓰기지연 저장소에 넣는다 
    
    tx.commit(); // 쓰기지연 sql저장소에있던 애들이 flush되고 커밋된다. 
    コミット前にINSERT sqlを実行せず、コミットした瞬間にDBに送信

    変更の検出

                Member member = em.find(Member.class, 150L);
                member.setName("ZZZZZ"); 
    //            em.persist(member); // 이부분호출해야되는거 아니야? 아니다 리스트,컬렉션에서 값을 변경하고 다시 집어넣냐? 아니거든
                tx.commit();
    updateクエリーが終了します.
    その理由は、永続性コンテキストにあります.

    スナップショットは、最初のキャッシュにも存在します.
    この値はスナップショットとして初期読取点の状態を表示します.
    提出された時点でJPAが比較する.末尾とスナップショット.
    変更が検出された場合、updateクエリは、遅延書き込みのsqlリポジトリに格納されます.
    そしてコミットします.

    更新


    永続性コンテキストへの変更をデータベースに反映
  • 変更検出
  • 遅延書き込みのsqlリポジトリには、
  • 修正エンティティ
  • が登録する.
  • クエリーをdbのsqlリポジトリ
  • に送信する
                Member member = new Member(200L, "member200");
                em.persist(member);
    
                em.flush(); //강제로 호출 이시점에 insert쿼리가 나감
                System.out.println("=======");
                
                tx.commit();
  • 持続コンテキスト
  • をクリアしない

    じゅんれんぞくじょうたい


    persistに入れると、永続的な状態になります.
    findを使用してクエリーを行う場合、プライマリキャッシュにない場合はdbからクエリーが取得され、クエリーが実行されます.この場合も永続的です.
    Em.detach(member)/持続性管理x,jpaは管理しません.

    オブジェクトとテーブルのマッピング


    @Entity

  • JPAが管理するエンティティ

  • JPAマッピングを使用するクラスは必須です

  • 必要な基本作成者(JPA仕様上)
    =>ライブラリがオブジェクトをreplicationに動的にエージェントする場合に必要

  • final、enum、interface、および内部クラスは使用できません

  • 保存するフィールドでfinalxを使用する
  • データベース・スキーマのサブプロパティ

  • アプリケーションのロード時に作成される文
  • 方言を使用してdbに適したddl
  • を作成する
  • は、開発装置(生産においてxを用いる)
  • のみに用いる.

    アノテーションのアウトラインが削除されると、既存のテーブルが消去され、作成されます.
    updateに値を割り当てると、変更部分のみが実行されます(alter文)
    値をvalidateとして使用すると、エンティティとテーブルが正常にマッピングされているかどうかを確認します.
    操作手順にはcreate、create-dropが含まれます
    (作成完了後にテーブルを削除)updateは絶対に使用できません
    テストサーバ、開発サーバはなるべく使用しない方が良いでしょう.
    検証の程度は悪くないと思います.
    ローカルサーバのみで自由...

    フィールドとカラムのマッピング



    なぜエンティティには基本的な作成者が必要ですか?


    JPAはHibernateが内部でレプリケーションを使用してオブジェクトを作成することを実現します.
    
    
    public class Application {
    
        public static void main(String[] args){
            
              Class<?> userClass = Class.forName("git.demo.domain.member.Member");
            Constructor<?> constructor = userClass.getConstructor(); // 런타임 에러지점 
            Member member =(Member) constructor.newInstance(); // User의 인스턴스생성
            System.out.println(member);
            
        }
    }
    JAva replicationではジェネレータのパラメータ情報を取得できません.コンストラクション関数がなく、パラメータのコンストラクション関数のみが存在する場合、replicationはオブジェクトを作成できません.

    @Column



    insertable, updateable


    登録、変更可能
    更新可能をfalseに設定した場合は変更されません

    nullable = false


    notnull条件が必要です

    unique = true


    独特の制限条件が設定されますが、あまり使いにくいです.

    @Enumatedのデフォルトはordinalです
    そのため、Stringに変えたほうがいいです.
    どうしたんですか.なぜなら、enumに値を追加すると、enum値自体の順序が変更されるからです.

    LOB


    フィールドタイプはCLOB、残りはBLOB

    プライマリ・キーのマッピング


    それぞれの戦略でどれを使うか.
    PKは、業務に全く関係のない生成鍵(代替鍵)+Long型を用いることが望ましい
    (身分証明書番号はPKですが、講師の身分証明書番号が受け入れられないポータルサイトの仕事の例)

    プライマリ・キーの直接割り当て


    @ID

    基本キー弟聖戦略


    @GeneratedValue=デフォルトキーが自動的に生成され、ポリシーを設定できます.
    IDENTITY:DBに委任
    ->コミット前にinsertクエリーを解放する
    @Entity
    public class Board{
    
    	@Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        ...
    }
    
    
    public static void main{
    	Board board = new Board();
        em.persist(board);
        print("board.id= " + board.getId()); //1출력 
    }
    SEQUENCE:DBシーケンスを使用してプライマリ・キーを割り当てる
    ->シーケンスポリシーであると判断した場合、値を永続性コンテキストに挿入しようとすると、DBシーケンスクエリ識別子が使用され、クエリの識別子がエンティティに割り当てられ、永続性コンテキストに格納されます.
    IDENTITY:エンティティをdbに保存し、識別子をクエリーしてエンティティに割り当てます.
    SEQUENCE:DBシーケンスクエリー識別子を使用して、クエリーのアスタリスクをエンティティに割り当て、永続性コンテキストに格納します.
    AUTO=方言による自動選択、DB変更はコード修正不要
    @SequenceGenerator(name = "MEMBER_SQE_GENERATOR",sequenceName = "MEMBER_SEQ"
                        ,initialValue = 1 , allocationSize = 50)
    /**
     * 미리 50개를 땡긴다. 50개를 db에 미리올려놓고, 메모리에서 그 개수만큼 쓰는방식
     * 여러was가있어도 동시성이슈가없고
     * 두번호출시
     * SEQ = 1  // 문제가있나보네?라고 인식하고 한번더 호출
     * SEQ = 51  // 애플리케이션이 2를쓰고
     * SEQ = 51 //  3을쓸것이다.
     * em.persist(member1) // 1이 처음 호출되고 재호출해서 51을 쓰게되고
     * em.persist(member2) // 51//2 메모리에서 사용
     * em.persist(member3) // 51//3 메모리에서 사용
     * 51번을 만나는순간 50개를 더 떙겨야되기때문에 next call이 호출된다
     * 이것은 allocationSize에 따라 달라진다. 
     *
     */
    
    
    
      /**
         * GeneratedValue = 
         
         * IDENTITY = 기본키 생성을 DB에 위임 난 모르겠고 db너가 알아서해줘라
         * => 이 케이스에서는 특이하게 커밋하는시점에 쿼리가 날라가는 일반상태와달리 커밋전 바로 insert쿼리가 날아간다.(영속성 관리하려면 pk값이 필요한데, pk값을 db에위임하기때문에)
         * SEQUENCE = DB시퀀스 오브젝트 사용 , 오라클은 @SequenceGenerator 가필요하다
         * => 시퀀스전략을 확인하면, 영속성컨텍스트에 넣으려고할때 db에서 값을얻어와서 id값을 넣어준다. 그후 영속성컨텍스트에 저장한다.
         
         allocationSize 
         *
         * */
        
        /**
         * Long을쓰는게 좋은이유 : 데이터가 많아져 10억이 넘는경우 그때 타입을 바꾸는것보다 Integer를 써야하는데 Long을쓰는상황이낫다
         *
         */