JPA學習筆記

          目錄
          目錄 1
          一、JPA基礎(chǔ) 2
          1.1 JPA基礎(chǔ) 2
          1.2JPA開發(fā)過程 3
          1.3 實體的生命周期及實體管理器常用方法 4
          二、環(huán)境搭建 5
          2.1 添加JPA支持 6
          2.2 添加配置文件 6
          2.3測試配置 6
          2.4 環(huán)境搭建附表 6
          三、常用注解 12
          3.1 批注完全參考 12
          3.2 ID相關(guān)的 12
          3.3主鍵生成策略 13
          3.4字段、添加字段、添加表關(guān)聯(lián) 13
          3.5映射相關(guān) 14
          3.6其他 14
          四、JPA映射 14
          4.1一對一映射 15
          4.1.1共享主鍵映射 15
          4.1.2關(guān)聯(lián)外鍵映射 17
          4.1.3添加表關(guān)聯(lián) 17
          4.2一對多關(guān)聯(lián) 18
          4.2.1添加字段的一對多、多對一關(guān)聯(lián) 18
          4.2.2添加表的一對多、多對一關(guān)聯(lián) 19
          4.3多對多關(guān)聯(lián) 20
          4.4繼承映射 21
          五、JPQL 21
          六、常見異常 22

           

           

           

           

          一、JPA基礎(chǔ)
          1.1 JPA基礎(chǔ)
          JPA: java persistence api 支持XML、JDK5.0注解倆種元數(shù)據(jù)的形式,是SUN公司引入的JPA ORM規(guī)范


          元數(shù)據(jù):對象和表之間的映射關(guān)系


          實體: entity,需要使用Javax.persistence.Entity注解或xml映射,需要無參構(gòu)造函數(shù),類和相關(guān)字段不能使用final關(guān)鍵字
           游離狀態(tài)實體以值方式進行傳遞,需要serializable


          JPA是一套規(guī)范、有很多框架支持(如Hibernate3.2以上、Toplink,一般用Hibernate就行 oracle可以用toplink)
            
           JPQL
           1、與數(shù)據(jù)庫無關(guān)的,基于實體的查詢語言
           2、操作的是抽象持久化模型
           3、JPQL是一種強類型語言,一個JPQL語句中每個表達式都有類型 
           4、EJBQL的擴展
           5、支持projection(可以查詢某個實體的字段而不需要查詢整個實體)、批量操作(update、delete)、子查詢、join、group by having(group by聚合后 having 聚合函數(shù) 比較 條件)
           
           
           弱類型語言:沒有明顯的類型、根據(jù)情況變化、容易出錯
           強類型語言:沒個變量都有固定的類型。不容易出錯
           
           
           雖然JPA規(guī)范中明確表示無法訪問一個集合關(guān)系字段
           
           抽象模型類型:JPQL規(guī)范將一個實體(屬性)中所飲食的各種類型稱為抽象模型類型
            狀態(tài)字段
            關(guān)聯(lián)字段
            
           查詢多個字段查出來的是個對象值數(shù)組
          1.2JPA開發(fā)過程
           JPA配置文件聲明持久化單元 --> 配置文件persistence.xml
           編寫帶標注的實體類
           編寫Dao類
           
           
           
          xml配置
           
           事務類型分為:RESOURCE_LOCAL
          本地事務、JTA(java事務API)
           
           注解
            @Entity  將JavaBean標注為一個實體 name屬性
            @Table  數(shù)據(jù)庫中的表,name名稱、catalog數(shù)據(jù)庫名 @Secondary Table/@Secondary Tables多個表
            @Id   定義了實體的主鍵信息
            @GeneratedValue逐漸省城策略
               @GeneratedValue(Strategy = GenerationType.SEQUENCE)
               @SequenceGenerator(name="SEQ_TEST",sequenceName="User_SEQ",allocationSize=25)
            @column  屬性、字段對應的表字段
            @Temporal 屬性是時間類型的話可以細分
               DATE  java.sql.Date
               TIME  java.sql.Time 
               TIMESTAMP java.sql.Timestamp
            @Lob  標注CLOB、BLOB
            @Base 是否延遲加載@Base(fetch = FETCHTYPE.LAZY/FETCHTYPE.EAGER) 
            @Transient 實體bean中,所有非static、非transient狀態(tài)變量、字段都要被持久化
               如果有字段、變量在數(shù)據(jù)庫中沒有對應,標注為transient就可以不被持久化
            標注方式: 標注在字段上
               標注在變量上
            
           實體類寫法:
            1、必須有無參的構(gòu)造函數(shù)
            2、沒有final類型的變量或方法
            3、不可以是public類型的,只能通過get、set方法讀寫
            
           管理實體
            Persistence
            EntityManagerFactory
            EntityManager
            
            Persistence.createEntityManagerFactory('persistence.xml中配置的persistence unit').createEntityManager()獲取EntityManager
            
          1.3 實體的生命周期及實體管理器常用方法  
            EntityManager聲明周期    Java對象   實體管理器    數(shù)據(jù)庫
             1、 新實體(new)     存在    不存在     不存在    
             2、持久化實體(managed)   存在    存在     存在
             3、分離的實體(detached)   不存在    不存在     存在
             4、刪除的實體(removed)   存在    存在     不存在
             
             
                  new  
                  ↓persist()  
               find()  ↓  commit()、clear()
              DB  → → → → → → managed  → → → → → → detached
                  ↓   ←merge()
                  ↓   
                  ↓remove()
                  removed
             常用方法
             1、persist(Object)       持久化
             2、remove(Object)       刪除對象
             3、find(Class entityClass,Object key)  根據(jù)主鍵查詢
             4、flush()         實體與底層同步,執(zhí)行sql
             5、createQuery()       創(chuàng)建JPQL查詢對象
             5、createNativeQuery()      根據(jù)普通SQL查詢
             5、createNamedQuery()      命名查詢@NamedQuerie標注 
             5、merge(Object)       將一個detached的實體持久化到EntityManager中
             5、close()         關(guān)閉管理器
          ———————————————————————————————————————
          javax.persistence.Query   
          int executeUpdate()   執(zhí)行更新、刪除、添加
          Object getSingleResult() 執(zhí)行查詢(返回一條記錄) 
          List getResultList()  執(zhí)行查詢(返回結(jié)果鏈表)
          Query setParameter(int position,object value) 給Query對象設置參數(shù)
          Query setMaxResults(int maxResult)    給Query對象設置返回數(shù)
          Query setFirstResult(int firstResult)  給Query對象設置返回偏移
              
              
          參數(shù)查詢(只能用一種)
               命名參數(shù)查詢 "select u from User where id = :uid";  setParameter("uid",value);
               位置參數(shù)查詢

          ------------------------------------------------------------

          Person person = em.find(Person.class,1);
          //相當于Hibernate的get
          Person person = em.getReference(Person.class,1);  
          //相當于Hibernate的load返回一個代理對象
             //注意延遲加載時的 事務沒關(guān)閉的時候才好用

          find 如果找不到返回的是個null,這時候下面在調(diào)用null的方法報nullpoint異常
          reference相當于延遲加載  如果找不到,會在第一次使用就報EntityNotFound異常
               
            回調(diào)函數(shù)(相當于攔截器,下面的方法執(zhí)行前后調(diào)用指定的方法)     
              @Prepersist      
              @PostPersist
              @PreRemove
              @PostRemove
              @PreUpdate
              @PostUpdate
              @PostLoad    載入實體時(find、查詢、refresh)

          -----------------------------------------------------------------
          二、環(huán)境搭建
          2.1 添加JPA支持
          1、準備JPA用到的jar包(JPA支持包)
          2、window → preferences → Java → BuildPath → User Libraries
              →new  User Library
              →Add  Jars

          3、項目   → 右鍵 → properties(alt+Enter)
          → Java Build Path  → Libraries
              → Add Library  → User Library  → 自己定義的JPA支持包

          2.2 添加配置文件
           1、項目中SRC目錄下添加META-INF目錄(與Web項目下META-INF同名)
           2、在新添加的META-INF中添加配置文件persistences.xml
            persistence.xml配置信息 (Hibernate)
            數(shù)據(jù)庫連接信息查詢
            主要配置信息:
             事務類型:本地事務、JTA事務
          JPA供應商
            數(shù)據(jù)庫驅(qū)動、URL、User、Password
           3、在SRC目錄下添加log4j.properties文件(顯示數(shù)據(jù)庫操作信息的)


          2.3測試配置
           1、MySQL測試數(shù)據(jù)庫
            2、實體注解
           3、JUNIT測試方法

           

           


          2.4 環(huán)境搭建附表

          persistence.xml配置信息
          <?xml version="1.0" encoding="UTF-8"?>
          <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence  <!-- name="持久化單元命名"  transaction-type="本地事務/JTA" -->
           <persistence-unit name="JPA" transaction-type="RESOURCE_LOCAL">
            <!-- 供應商 -->
            <provider>org.hibernate.ejb.HibernatePersistence</provider>
            
            
            <properties>
             <!-- 參數(shù):數(shù)據(jù)庫驅(qū)動名、地址、用戶、密碼、方言、顯示執(zhí)行SQL語句 -->
             <property name="hibernate.connection.driver_class" value=""/>
             <property name="hibernate.connection.driver_class" value="org.gjt.mm.mysql.Driver"/>
             <property name="hibernate.connection.url" value="jdbc:mysql://127.0.0.1:3306/JPA"/>
             <property name="hibernate.connection.username" value="root"/>
             <property name="hibernate.connection.password" value="123456"/>
             <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
             <property name="hibernate.show_sql" value="true"/>
             
             <!-- 其他設置 -->
             <property name="minPoolSize" value="5"/>
             <property name="initialPoolSize" value="10"/>
             <property name="idleConnectionTestPeriod" value="120"/>
             <property name="acquireIncrement" value="10"/>
             <property name="checkoutTimeout" value="3600"/>
             <property name="numHelperThreads" value="4"/>
             <property name="maxStatements" value="400"/>
             <property name="maxStatementsPerConnection" value="20"/>
             <property name="maxIdleTime" value="180"/>
             <property name="acquireRetryAttempts" value="30"/>
             <property name="maxPoolSize" value="200"/>
            
            </properties>
           </persistence-unit>
          </persistence>

          自動創(chuàng)建|更新|驗證數(shù)據(jù)庫表結(jié)構(gòu)。如果不是此方面的需求建議set value="none"。
          容易造成數(shù)據(jù)丟失,一般在測試的時候才用

          <property name="hibernate.hbm2ddl.auto" value="create"></property>、validate  驗證數(shù)據(jù)庫表結(jié)構(gòu)
          create  每次加載Hibernate都會刪除上一次的表結(jié)構(gòu),根據(jù)model重新生成
          create-drop每次加載創(chuàng)建,sessionFactory關(guān)閉表就自動刪除
          update  加載Hibernate就更想你表結(jié)構(gòu)

          環(huán)境測試代碼
          實體注解
          @Entity
          @Table(name="Person")
          public class Person {
           @Id
           @Column(name="pid")
           private Integer id;
           @Column(name="pname")
           private String name;
           public Integer getId() {
            return id;
           }
           public void setId(Integer id) {
            this.id = id;
           }
           public String getName() {
            return name;
           }
           public void setName(String name) {
            this.name = name;
           }
           
          }

          JUNIT測試方法
          public EntityManager testGetEM(){
            EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPA");
            EntityManager em = emf.createEntityManager();
            return em;
           }
           public void testAddPerson(){
            Person p = new Person();
            p.setId(1);
            p.setName("ader");
            EntityManager em = testGetEM();
            EntityTransaction et = em.getTransaction();
            try {
             et.begin();
             em.persist(p);
             et.commit();
            } catch (Exception e) {
             e.printStackTrace();
            }
           }

           MySQL測試數(shù)據(jù)庫
          drop database if exists jpa;
          create database jpa;
          use jpa;
          drop table if exists person;
          drop table if exists  ident;
          drop table if exists  rel;
          create table person(
           pid int primary key auto_increment,
           pname varchar(50)
          )
          ;
          create table ident(
           iid int primary key auto_increment,
           iname varchar(50)
          );
          create table rel(
           personid int,
           identid int
          );

           

           

          JPA支持包
          antlr-2.7.6.jar
          cglib-2.1.3.jar
          classes12.jar
          commons-collections-3.1.jar
          dom4j-1.6.1.jar
          ehcache-1.2.3.jar
          ejb3-persistence.jar
          hibernate3.jar
          hibernate-annotations.jar
          hibernate-cglib-repack-2.1_3.jar
          hibernate-commons-annotations.jar
          hibernate-entitymanager.jar
          javassist-3.4.GA.jar
          jta-1.1.jar
          log4j-1.2.15.jar
          persistence-api-1.0.jar
          slf4j-api-1.5.2.jar
          slf4j-log4j12.jar


          Hibernate核心包(8個文件):hibernate-distribution-3.3.1.GA.ZIP
          -----------------------------------------------------------------
          hibernate3.jar
          lib\bytecode\cglib\hibernate-cglib-repack-2.1_3.jar (CGLIB庫,Hibernate用它來實現(xiàn)PO字節(jié)碼的動態(tài)
          生成,非常核心的庫,必須使用的jar包)
          lib\required\*.jar
          Hibernate注解包(3個文件):hibernate-annotations-3.4.0.GA.ZIP
          -----------------------------------------------------------------
          hibernate-annotations.jar
          lib\ejb3-persistence.jar, hibernate-commons-annotations.jar
          Hibernate針對JPA的實現(xiàn)包(3個文件):hibernate-entitymanager-3.4.0.GA.ZIP
          -----------------------------------------------------------------
          hibernate-entitymanager.jar
          lib\test\log4j.jar, slf4j-log4j12.jar

           


          數(shù)據(jù)庫連接信息查詢
          1、Hibernate JDBC屬性
          屬性名  用途
          hibernate.connection.driver_class jdbc驅(qū)動類
          hibernate.connection.url jdbc URL
          hibernate.connection.username 數(shù)據(jù)庫用戶
          hibernate.connection.password 數(shù)據(jù)庫用戶密碼
          hibernate.dialect 數(shù)據(jù)庫方言

          2、驅(qū)動包
          Db2:db2java.jar(JDBC直連)
             :db2jcc.jar(Hibernate要用到此驅(qū)動jar文件和上面的驅(qū)動jar文件)
          sybase:jconn3d.jar
          MSSQL:msbase.jar+mssqlserver.jar+msutil.jar
          MySQL:mysql-connector-java-3.1.12-bin.jar
          Oracle10g:ojdbc14.jar

          3、連接字符串(可以先添加驅(qū)動包然后到包里找Driver.class)
          a、MSSQL
          驅(qū)動:com.microsoft.jdbc.sqlserver.SQLServerDriver
          地址:jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=數(shù)據(jù)庫

          b、Oracle10g
          驅(qū)動:oracle.jdbc.driver.OracleDriver
          地址:jdbc:oracle:thin:@127.0.0.1:1521:全局標識符

          c、MySQL
          驅(qū)動:org.gjt.mm.mysql.Driver
          地址:jdbc:mysql://127.0.0.1:3306/數(shù)據(jù)庫

          d、Access
          驅(qū)動:sun.jdbc.odbc.JdbcOdbcDriver
          地址:jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ=c:\\demodb.mdb

          e、DB2
          驅(qū)動:COM.ibm.db2.jdbc.net.DB2Driver
          地址:jdbc:db2://127.0.0.1:6789/demodb
          4、Hibernate SQL方言 (hibernate.dialect)
          RDBMS 方言
          DB2 org.hibernate.dialect.DB2Dialect
          DB2 AS/400 org.hibernate.dialect.DB2400Dialect
          DB2 OS390 org.hibernate.dialect.DB2390Dialect
          PostgreSQL org.hibernate.dialect.PostgreSQLDialect
          MySQL org.hibernate.dialect.MySQLDialect
          MySQL with InnoDB org.hibernate.dialect.MySQLInnoDBDialect
          MySQL with MyISAM org.hibernate.dialect.MySQLMyISAMDialect
          Oracle (any version) org.hibernate.dialect.OracleDialect
          Oracle 9i/10g org.hibernate.dialect.Oracle9Dialect
          Sybase org.hibernate.dialect.SybaseDialect
          Sybase Anywhere org.hibernate.dialect.SybaseAnywhereDialect
          Microsoft SQL Server org.hibernate.dialect.SQLServerDialect
          SAP DB org.hibernate.dialect.SAPDBDialect
          Informix org.hibernate.dialect.InformixDialect
          HypersonicSQL org.hibernate.dialect.HSQLDialect
          Ingres org.hibernate.dialect.IngresDialect
          Progress org.hibernate.dialect.ProgressDialect
          Mckoi SQL org.hibernate.dialect.MckoiDialect
          Interbase org.hibernate.dialect.InterbaseDialect
          Pointbase org.hibernate.dialect.PointbaseDialect
          FrontBase org.hibernate.dialect.FrontbaseDialect
          Firebird org.hibernate.dialect.FirebirdDialect

          -----------------------------------------------------------------
          三、常用注解
          3.1 批注完全參考
          @Entity要將 Java 類指定為 JPA 實體,請使用批注
          詳細信息
           
          3.2 ID相關(guān)的
          復合主鍵需要
          1、 實現(xiàn)序列話
          2、 重寫hascode、equal方法
          3、 有構(gòu)造方法
          @Embeddable 復合主鍵設置可以被引用
          @EmbeddedId 引用獨立復合主鍵ID
          3.3主鍵生成策略
          使用Hibernate的主鍵生成策略生成字符串主鍵
          @Id
          @GenericGenerator(name="generator",strategy="uuid")
          @GeneratedValue(generator="generator")
          @Column(name="id")

          使用Hibernate的主鍵生成策略與其他類共享主鍵
          @Id
           @GenericGenerator(name = "generator",
                       strategy = "foreign",
                        parameters = {
                        @Parameter(name = "property", value = "person")
                      })
            @GeneratedValue(generator = "generator")
          @Column(name="cid")
          3.4字段、添加字段、添加表關(guān)聯(lián)
          @Column 持久化字段
           可添加、可更新、可為空
           長度、表名、字段名、unique是否唯一

          @JoinColumn
           name 列名
          referencedColumnName指向?qū)ο蟮牧忻?br />unique約束唯一
          @JoinColumns多個連接的列
          @JoinColumns({
          @JoinColumn(name="ADDR_ID", referencedColumnName="ID"),
          @JoinColumn(name="ADDR_ZIP", referencedColumnName="ZIP")
              })
          @JoinTable
          @JoinTable(
          name="EJB_PROJ_EMP",
          joinColumns=@JoinColumn(name="EMP_ID", referencedColumnName="ID"),
          inverseJoinColumns=@JoinColumn(name="PROJ_ID", referencedColumnName="ID")
          )

          3.5映射相關(guān)
          @OneToOne
          @ManyToOne
          @ManyToMany
          cascade級聯(lián)、CURD
          fetch一次性全部讀取相關(guān)對象,還是lazy加載
          optional 關(guān)聯(lián)對象是否允許為空
          targetEntity關(guān)聯(lián)對象


          3.6其他
           排序
          @OrderBy("lastname ASC", "seniority DESC")

          共享主鍵
          @PrimaryKeyJoinColumn

          標注為非持久話對象
          @Transient
          時間類型
          @Temporal(TemporalType.…………)
          枚舉類型
          @Enumerated(EnumType.…………)

           

           

          @Lob //聲明屬性對應的是一個大文件數(shù)據(jù)字段。
          @Basic(fetch = FetchType.LAZY) //設置為延遲加載,當我們在數(shù)據(jù)庫中取這條記錄的時候,不會去取
          -----------------------------------------------------------------
          四、JPA映射
          4.1一對一映射
          4.1.1共享主鍵映射
           1、一端提供主鍵、一端共享主鍵
            設置生成策略generator,主鍵值gereratedValue(generator=””)
            uuid字符串ID
            foreign引用別人ID作為自己的主鍵(需要設置引用對象參數(shù))
           2、oneToOne
            targetEntity 關(guān)聯(lián)的目標對象,是類名.class形式
          fetch   抓去策略,有關(guān)聯(lián)的一起抓去、還是lazy加載
          cascade   級聯(lián)
          mappedBy  本對象被映射為*(在PrimaryKeyJoinColumn的另一端)
           3、PrimaryKeyJoinColumn設置在一端即可
            name    自身字段
            referenceColumnName指向?qū)ο蟮淖侄?br /> 注意:
          只要一個PrimaryKeyJoinColumn,另一端的oneToOne 設置mappedBy
          都只有一個
          注意:
          1、向共享主鍵的對象設置提供主鍵的對象,然后持久化共享主鍵對象
           2、需要設置級聯(lián)
          3、共享主鍵端維護關(guān)系、提供主鍵端被維護使用mappedBy

           
          Person提供主鍵
           @Id
              @GenericGenerator(name = "generator", strategy = "uuid")
              @GeneratedValue(generator = "generator")
           @Column(name="pid")
           private String id;
           
           @Column(name="pname",length=2)
           private String name;

           @OneToOne(mappedBy="person",fetch=FetchType.EAGER,targetEntity=Idcard.class)
           private Idcard idcard;

           Idcard共享主鍵
           @Id
           @GenericGenerator(name = "generator",
                      strategy = "foreign",
                      parameters = {
                        @Parameter(name = "property", value = "person")
                      })
              @GeneratedValue(generator = "generator")
           @Column(name="cid")
           private String id;
           @Column(name="cno")
           private String no;
           @OneToOne(targetEntity=Person.class,fetch=FetchType.EAGER,cascade=CascadeType.ALL)
           @PrimaryKeyJoinColumn(name="id",referencedColumnName="id")
           private Person person;

           @Id
           @GenericGenerator(name = "generator",
                      strategy = "foreign",
                      parameters = {
                        @Parameter(name = "property", value = "person")
                      })
                      @GeneratedValue(generator = "generator")
           @Column(name="cid")
           private String id;
           @Column(name="cno")
           private String no;
           @OneToOne(mappedBy="idcard",fetch=FetchType.EAGER,targetEntity=Person.class)
           private Person person;


          使用共享主鍵關(guān)聯(lián)
          Person p = new Person();
             p.setName("ader");
             Idcard idcard = new Idcard();
             idcard.setNo("321321");
             idcard.setPerson(p);

           

           


          4.1.2關(guān)聯(lián)外鍵映射
           關(guān)系的維護端
          @OneToOne(級聯(lián))
           @JoinColumn(name="本表中關(guān)聯(lián)字段",referencedColumnName="指向字段")
           被維護端
          @OneToOne(mappedBy=””)

          關(guān)系維護端添加一個字段作為外鍵指向被維護段。被維護端聲明mappedBy
          @Entity
           @Table(name="Test_Trousers")
           public class Trousers {
              @Id
              public Integer id;
              @OneToOne
              @JoinColumn(name = "zip_id")
              public TrousersZip zip;
           }

           @Entity
           @Table(name="Test_TrousersZip")
           public class TrousersZip {
              @Id
              public Integer id;
              @OneToOne(mappedBy = "zip")
              public Trousers trousers;
           }
          4.1.3添加表關(guān)聯(lián)
           添加關(guān)聯(lián)表的一一關(guān)聯(lián)
           @OneToOne
           @JoinTable(name ="關(guān)聯(lián)表名稱",
            joinColumns = @JoinColumn(name="關(guān)聯(lián)本表的字段"),
            inverseJoinColumns = @JoinColumn(name="要關(guān)聯(lián)的表的字段")
           )
           @Entity
           @Table(name="Test_People")
           public class People {
              @Id
              public Integer id;
              @OneToOne
              @JoinTable(name ="TestPeoplePassports",
                joinColumns = @JoinColumn(name="perple_fk"),
                inverseJoinColumns = @JoinColumn(name="passport_fk")
              )
              public Passport passport;
           }

           @Entity
           @Table(name="Test_Passport")
           public class Passport {
              @Id
              public Integer id;
              @OneToOne(mappedBy = "passport")
              public People people;
           }

           

          4.2一對多關(guān)聯(lián)
            
            我們維護的多是他們的關(guān)系 而不是實體所以建議使用添加關(guān)系表
            在多的一端:添加字段、或者添加表 設置級聯(lián)添加
            在一端: mappedBy
            用法:new一個一的一端對象  set到多的對象中,在持久化多的一端

           4.2.1添加字段的一對多、多對一關(guān)聯(lián)
           manyToOne  多對一
           oneToMany    用一個set存放對象
          添加字段關(guān)聯(lián),一般是在多的一端維護關(guān)系,設置級聯(lián)。一的一端mappedBy


           @Id
           @GenericGenerator(name="t1",strategy="uuid")
           @GeneratedValue(generator="t1")
           @Column(name="cid")
           private String cid;
           @Column(name="cname")
           private String cname;
           @OneToMany(fetch=FetchType.EAGER,mappedBy="cls")
           private Set<Student> studentSet;


           @Id
           @GenericGenerator(name="t2",strategy="uuid")
           @GeneratedValue(generator="t2")
           @Column(name="id")
           private String id;
           @Column(name="name")
           private String name;
           @ManyToOne(fetch=FetchType.EAGER,cascade=CascadeType.PERSIST,targetEntity=Clas.class)
           @JoinColumn(name="classid",referencedColumnName="cid")
           private Clas cls;


          4.2.2添加表的一對多、多對一關(guān)聯(lián)
           多的一端
          @Id
           @GenericGenerator(name="generator",strategy="uuid")
           @GeneratedValue(generator="generator")
           @Column(name="id")
           private String id;
           @Column(name="name")
           private String name;
           @ManyToOne(targetEntity=C.class,cascade = CascadeType.PERSIST)
           @JoinTable(name="csrel",
             joinColumns=@JoinColumn(name="sid",referencedColumnName="id"),
             inverseJoinColumns=@JoinColumn(name="cid",referencedColumnName="cid")
           )
           private C c;
           一的一端
           @Id
           @GenericGenerator(name="generator",strategy="uuid")
           @GeneratedValue(generator="generator")
           @Column(name="cid")
           private String id;
           @Column(name="cname")
           private String name;
           
           @OneToMany(targetEntity=S.class,mappedBy="c")
           private Set<S> sset;


          4.3多對多關(guān)聯(lián)
          添加表關(guān)聯(lián)

          假設Teacher 和 Student是多對多的關(guān)系,具體元數(shù)據(jù)聲明如下:
          pubic class Teacher{       
          @ManyToMany(targetEntity = Student.class, cascade = CascadeType.PERSIST)       
          @JoinTable(table = @Table(name = "M2M_TEACHER_STUDENT"),       
          joinColumns = @JoinColumn(name = "TEACHER_ID", referencedColumnName = "ID"), 
          inverseJoinColumns = @JoinColumn(name = "STUDENT_ID", referencedColumnName = "ID"))       
          public List<Student> getStudents() {
          return students;
          }                                     
          }

          public class Student{       
          @ManyToMany(targetEntity = Teacher.class, mappedBy = "students")       
          public List<Teacher> getTeachers() {              
          return teachers;        }
          }
          ************************************************
          Student student = em.find(Student.class, 1);
          Teacher teacher = em.getReference(Teacher.class, 1);
          student.removeTeacher(teacher);
          在一個事務中
          ************************************************


          4.4繼承映射
          繼承關(guān)系映射在同一張表中

          @Entity
          @Table(name = "customer")
          @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
          @DiscriminatorColumn(name = "flag", discriminatorType = DiscriminatorType.STRING)
          public class Customer{
          }

          @Entity
          @DiscriminatorValue(value = "A")
          public class CustomerA extends Customer{
          }

          @Entity
          @DiscriminatorValue(value = "B")
          public class CustomerB extends Customer{
          }

          SINGLE_TABLE:父子類都保存到同一個表中,通過字段值進行區(qū)分。
          JOINED:父子類相同的部分保存在同一個表中,不同的部分分開存放,通過表連 接獲取完整數(shù)據(jù);

          TABLE_PER_CLASS:每一個類對應自己的表,一般不推薦采用這種方式。
          --------------------------------------------------------------
          五、JPQL
          JPQL 是一種強類型語言,一個JPQL語句中每個表達式都有類型。
            JPQL類似Hibernate的HQL
          單字段 返回具體類型
          多字段 返回多個具體類型的數(shù)組

          查詢單個字段,返回List   List<String>
          查詢單個字段,返回List 只有一條記錄 還是List<String>

          查詢多個字段,返回List   List<Object[]>  對象數(shù)組由多個字段值組成
          查詢多個字段,返回List 只有一條記錄 還是List<Object[]>


           一條記錄getSingleResult 多條記錄
          單一字段 單一值對象 List<Object>
          多個字段 值對象組成的數(shù)組 List<Object[]>
          實體對象 一個對象entity List<entity>

          JPA操作的實體
           需要@Entity name注解
           或者是限定詞(com.sunyard.User為全稱,User為限定詞)
          標識變量
           select  u from User;   //這里u就是標識變量
          路徑表達式
           表示福報 +  訪問操作符(.) + 狀態(tài)字段/關(guān)聯(lián)字段
           狀態(tài)字段:包括一個實體不代表關(guān)聯(lián)關(guān)系的任何字段
           關(guān)聯(lián)字段:包括了實體中任何有關(guān)聯(lián)關(guān)系的字段或者屬性
          參數(shù)(select u from User u where uid=?1 and uname=:name)
           ?1    位置參數(shù)setParameter(’name’,’value’)
           :name   命名參數(shù)setParameter(’name’,’value’)
           不建議在SQL語句中直接寫參數(shù),防止注入。

          六、常見異常
          1、異常信息:org.hibernate.hql.ast.QuerySyntaxException: person is not mapped
           異常環(huán)境:查詢
           異常原因:查詢語句中Person類沒有大寫

          2、java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to java.lang.String
           異常環(huán)境:查詢、遍歷顯示
           異常原因:轉(zhuǎn)型出錯
           
          3、javax.persistence.NonUniqueResultException: result returns more than one elements
           異常環(huán)境:查詢、getSingleResult
           異常原因:getSingleResult只能獲取一條數(shù)據(jù),而查詢語句返回的是多條數(shù)據(jù)
           
          4、 org.hibernate.PropertyValueException: not-null property references a null or transient value: com.sunyard.entities.Person.name
           異常環(huán)境:數(shù)據(jù)插入
           異常原因:JPA的Entity中一個屬性定義為nullable=false,插入數(shù)據(jù)該字段為null

          5、 執(zhí)行添加沒反應、沒異常
           異常原因:沒有開啟事務、沒有提交事務
           
          6、javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.sunyard.entities.Person
           異常環(huán)境:OneToOne 共享主鍵關(guān)聯(lián)
           異常原因:一對一中,一個提供主鍵、另一個共享其主鍵,共享主鍵的對象可以set 提供主鍵的對象 然后添加到數(shù)據(jù)庫中
              方向弄反了 后果就是沒人提供主鍵
             
          7、org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing:   
           異常環(huán)境:多對一添加
           異常原因:在多的一端維護 ,沒有添加級聯(lián)
           
          8、javax.persistence.PersistenceException: [PersistenceUnit: JPA] Unable to configure EntityManagerFactory
           異常原因:很多、實體管理器Factory沒有成功創(chuàng)建,是注解的問題
          9、org.hibernate.MappingException: Unable to find column with logical name: sid in org.hibernate.mapping.
           異常環(huán)境:添加表做多對一關(guān)聯(lián)映射
           異常原因:表字段寫反了,name添加表字段名referencedColumnName指向本表字段名

          posted on 2012-11-01 09:05 Mr.lu 閱讀(20244) 評論(3)  編輯  收藏

          評論

          # re: JPA學習筆記 2013-11-20 08:37 qunhao12

          說得很細很全面,收藏了  回復  更多評論   

          # re: JPA學習筆記 2015-06-12 18:02 zuidaima

          springdata jpa相關(guān)demo源代碼下載:http://zuidaima.com/share/kjpa-p1-s1.htm  回復  更多評論   

          # re: JPA學習筆記 2016-03-09 18:16 劉高潮

          非常實用  回復  更多評論   


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
           
          <2012年11月>
          28293031123
          45678910
          11121314151617
          18192021222324
          2526272829301
          2345678

          導航

          統(tǒng)計

          常用鏈接

          留言簿(2)

          隨筆檔案

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 青州市| 安康市| 济南市| 安徽省| 肇州县| 正镶白旗| 阜新市| 三河市| 涡阳县| 思南县| 盐山县| 潞城市| 界首市| 泉州市| 宜章县| 大关县| 波密县| 中山市| 昌乐县| 乡宁县| 财经| 渭南市| 郁南县| 二连浩特市| 清原| 南郑县| 西宁市| 胶州市| 阿拉尔市| 禹州市| 武乡县| 神农架林区| 阿坝县| 深水埗区| 西畴县| 康定县| 砚山县| 曲松县| 正定县| 萝北县| 辽阳市|