SSH框架之Hibernate第四篇

Hibernate中有两套实现数据库数据操作的方式 : 
        hibernate前3天讲解的都是 : hibernate自己的操作方式(纯XML配置文件的方式)
        另一种方式是基于JPA的操作方式(通过注解的方式替代之前的部分XML)
        
    JPA相关概念:
        1.1JPA概述 : (java的持久化规范(规范即接口))
            全称是 : Java Persistence API. 是SUN公司推出的一套基于ORM的规范.hibernate框架中提供了JPA的实现.
            JAP通过JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中.
        1.2JPA要明确的
            a. JPA是一套ORM规范(算是一个接口),hibernate实现了JPA规范(算是一个实现类).
            b. hibernate中有自己的独立ORM操作数据库方式,也有JPA规范实现的操作数据库方式.
            c. 在数据库增删改查操作中,我们hibernate和JPA的操作都要会.
        JPA和hibernate的关系?
            JPA是接口,hibernate是实现.
            所有的ORM框架都可以去实现JPA接口,通过JPA提供的一些接口来操作数据库的数据.
            
        JPA的使用 : 
            JPA是通过注解的方式来描述,对象和表的映射关系.
            之前的对象和表的映射关系配置是通过XML,今天要替换成注解的方式.
            
        注释 : 给程序员看的.
        注解 : 给程序来使用的.
            为什么要出现注解?
                一开始就是为了替代所有的XML配置文件.
                
                工作中两种方式结合使用 : 
                    配置文件 + 注解
                        如果是需要常常改动的程序 : 用配置文件.
                        如果是定义好了不需要更改的程序 : 注解.
                    
    2.1 2 JPA的环境搭建
        1 hibernate的环境(16个包)
        2 JPA的环境(1个包)
            
        2.2.2 创建配置文件
                要求:在src下面的META-INF文件夹下面创建一个名称为persistence.xml的文件。
            配置文件的内容:
                <?xml version="1.0" encoding="UTF-8"?>  
                <persistence xmlns="http://java.sun.com/xml/ns/persistence"  
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
                    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence  
                    http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"  
                    version="1.0">  
                    <!--Name属性用于定义持久化单元的名字 (name必选,空值也合法);   
                        transaction-type 指定事务类型(可选)    
                            取值:
                                JTA:默认值
                                RESOURCE_LOCAL
                    -->  
                    <persistence-unit name="myPersistUnit" transaction-type="RESOURCE_LOCAL">  
                       
                      <properties>    
                            <!-- 生成DDL的策略 -->
                               <property name="hibernate.hbm2ddl.auto" value="update" />  
                               <!-- 数据库的连接信息 -->    
                               <property name="hibernate.connection.driver_class" 
                                        value="com.mysql.jdbc.Driver" />    
                               <property name="hibernate.connection.url" 
                                        value="jdbc:mysql://localhost:3306/hibernate_jpa"/>  
                               <property name="hibernate.connection.username" value="root" />    
                               <property name="hibernate.connection.password" value="1234" />   
                               <!-- 指定方言 -->   
                               <property name="hibernate.dialect" 
                                        value="org.hibernate.dialect.MySQL5Dialect" />
                               <!-- 是否显示SQL语句 -->    
                               <property name="hibernate.show_sql" value="false" />
                               <!-- 是否格式化SQL语句 -->    
                               <property name="hibernate.format_sql" value="true" />   
                        </properties>    
                    </persistence-unit>  
                </persistence> 
    
        2.2.3 编写工具类,用于获取JPA的操作数据库对象
            public class HibernateUtils {
                //JPA的实体管理器工厂 : 相当于Hibernate的SessionFactory
                private static EntityManagerFactory em;
                //使用静态代码块赋值
                static {
                    //加载一次配置文件
                    //注意 : 该方法参数必须和persistence.xml中persistence-unit标签name属性取值一致
                    em = Persistence.createEntityManagerFactory("aaa");
                }
                /*
                 * 使用管理器工厂生产一个管理器对象
                 */
                //相当于获取连接
                public static EntityManager getEntityManager() {
                    return em.createEntityManager();
                }
            }
        
        jpa 的批量查询方式 :
            类似咋们之前学习的query方式查询 :
                1 : qr.getResultList() ;  类似之前的qr.list();
                2 : hibernate对于占位符?    以前是从0开始,jpa是从1开始.
                3 : 聚合 qr.getSingleResult();   类似之前的uniqueResult();
        
        2.2.4 编写实体类,并使用注解配置
            //级联保存 (保存客户的同时把关联的联系人给保存了)
            //jpa的注解里面 @OneToMany  添加属性cascade = CascadeType.PERSIST_STORE
            //根据一的一方保存多的一方的数据.
            // 级联保存 (保存联系人的同时把关联的客户给保存了)
            // jpa的注解里面 @ManyToOne  添加属性cascade=CascadeType.PERSIST
            //jpa的一对多没有普通删除
            // 级联删除
            // jpa的注解里面 @OneToMany  添加属性cascade=CascadeType.REMOVE (All)
        
            /**
             * 客户的实体类
             */
            @Entity
            @Table(name="cst_customer")
            public class Customer implements Serializable {

                @Id
                @GeneratedValue(strategy=GenerationType.IDENTITY)
                @Column(name="cust_id")
                private Long custId;
                
                @Column(name="cust_name")
                private String custName;
                
                @Column(name="cust_source")
                private String custSource;
                
                @Column(name="cust_industry")
                private String custIndustry;
                
                @Column(name="cust_level")
                private String custLevel;
                
                @Column(name="cust_address")
                private String custAddress;
                
                @Column(name="cust_phone")
                private String custPhone;
                    
                public Long getCustId() {
                    return custId;
                }
                public void setCustId(Long custId) {
                    this.custId = custId;
                }
                public String getCustName() {
                    return custName;
                }
                public void setCustName(String custName) {
                    this.custName = custName;
                }
                public String getCustSource() {
                    return custSource;
                }
                public void setCustSource(String custSource) {
                    this.custSource = custSource;
                }
                public String getCustIndustry() {
                    return custIndustry;
                }
                public void setCustIndustry(String custIndustry) {
                    this.custIndustry = custIndustry;
                }
                public String getCustLevel() {
                    return custLevel;
                }
                public void setCustLevel(String custLevel) {
                    this.custLevel = custLevel;
                }
                public String getCustAddress() {
                    return custAddress;
                }
                public void setCustAddress(String custAddress) {
                    this.custAddress = custAddress;
                }
                public String getCustPhone() {
                    return custPhone;
                }
                public void setCustPhone(String custPhone) {
                    this.custPhone = custPhone;
                }
                @Override
                public String toString() {
                    return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource
                            + ", custIndustry=" + custIndustry + ", custLevel=" + custLevel + ", custAddress=" + custAddress
                            + ", custPhone=" + custPhone + "]";
                }    
            }
        
        2.3 常用注解说明
            @Entity
                作用 : 指定当前类是实体类.写上此注解用于在创建SessionFactory/EntityManager时,加载映射配置.
                
            @Table
                作用 : 指定实体类和表之间的对应关系.
                属性 :
                    name : 指定数据库表的名称.
            
            @Id
                作用 : 指定当前字段是主键.
                
            @GeneratedValue
                作用 : 指定主键的生成方式.JPA的主键生成方式
                属性 : 
                    strategy : 指定主键生成策略.JPA支持四种生成策略,
        
            @Column : 
                作用 : 指定实体类属性和数据库表之间的对应关系.
                属性 : 
                    name : 指定数据库表的列名称.
                    unique : 是否唯一 .
                    nullable : 是否可以为空
                    inserttable : 是否可以插入
                    updateable : 是否可以更新
                    columnDefinition : 定义建表时创建此列的DDL.
                    secondaryTable : 从表名.如果此列不建在主表上(默认键在主表),该属性定义该列所在从表的名字.
            2.4主键生成策略
                通过annotation(注解)来映射hibernate实体的,基于annotation的hibernate主键标识为@Id, 
                其生成规则由@GeneratedValue设定的.这里的@id和@GeneratedValue都是JPA的标准用法。
                JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO。具体说明如下:
                2.4.1IDENTITY:主键由数据库自动生成(主要是自动增长型) 
                用法:
                    @Id  
                    @GeneratedValue(strategy = GenerationType.IDENTITY) 
                    private Long custId;
                2.4.2SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。 
                用法:
                    @Id  
                    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator="payablemoney_seq")      
                    @SequenceGenerator(name="payablemoney_seq", sequenceName="seq_payment")  
                说明:
                    @SequenceGenerator源码中的定义 
                    @Target({TYPE, METHOD, FIELD})   
                    @Retention(RUNTIME)  
                    public @interface SequenceGenerator {  
                        String name();  
                         String sequenceName() default "";  
                         int initialValue() default 0;  
                         int allocationSize() default 50;  
                    }  
                name:表示该表主键生成策略的名称,它被引用在@GeneratedValue中设置的“generator”值中。 
                    sequenceName:属性表示生成策略用到的数据库序列名称。 
                    initialValue:表示主键初识值,默认为0。 
                    allocationSize:表示每次主键值增加的大小,例如设置1,则表示每次插入新记录后自动加1,默认为50。
                    
                2.4.3AUTO:主键由程序控制。 
                用法:
                    @Id  
                    @GeneratedValue(strategy = GenerationType.AUTO)  


                2.5JPA的CRUD操作
                2.5.1保存
                /**
                     * 保存一个实体
                     */
                    @Test
                    public void testAdd(){  
                        //定义对象
                        Customer c = new Customer();
                        c.setCustName("传智学院");
                        c.setCustLevel("VIP客户");
                        c.setCustSource("网络");
                        c.setCustIndustry("IT教育");
                        c.setCustAddress("昌平区北七家镇");
                        c.setCustPhone("010-84389340");
                        EntityManager em=null;  
                        EntityTransaction tx=null;  
                        try{  
                            //获取实体管理对象
                            em=JPAUtil.getEntityManager();
                            //获取事务对象
                            tx=em.getTransaction();
                            //开启事务
                            tx.begin();
                            //执行操作
                            em.persist(c);
                            //提交事务
                            tx.commit();  
                        }catch(Exception e){
                            //回滚事务
                            tx.rollback();
                            e.printStackTrace();  
                        }finally{  
                            //释放资源
                            em.close();  
                        }    
                    }

                2.5.2修改
                    /**
                     * 修改
                     */
                    @Test
                    public void testUpdate(){  
                        //定义对象
                        EntityManager em=null;  
                        EntityTransaction tx=null;  
                        try{  
                            //获取实体管理对象
                            em=JPAUtil.getEntityManager();
                            //获取事务对象
                            tx=em.getTransaction();
                            //开启事务
                            tx.begin();
                            //执行操作
                            Customer c1 = em.find(Customer.class, 1L);
                            c1.setCustName("江苏传智学院");
                            //提交事务
                            tx.commit();  //使用JPA中快照机制实现更新
                        }catch(Exception e){
                            //回滚事务
                            tx.rollback();
                            e.printStackTrace();  
                        }finally{  
                            //释放资源
                            em.close();  
                        }    
                    }

                merge方法实现修改
                    @Test
                    public void testMerge(){  
                        //定义对象
                        EntityManager em=null;  
                        EntityTransaction tx=null;  
                        try{  
                            //获取实体管理对象
                            em=JPAUtil.getEntityManager();
                            //获取事务对象
                            tx=em.getTransaction();
                            //开启事务
                            tx.begin();
                            //执行操作
                            Customer c1 = em.find(Customer.class, 6L);
                            c1.setCustName("江苏传智学院");
                            em.clear();//把c1对象从缓存中清除出去
                            em.merge(c1);
                            //提交事务
                            tx.commit(); 
                        }catch(Exception e){
                            //回滚事务
                            tx.rollback();
                            e.printStackTrace();  
                        }finally{  
                            //释放资源
                            em.close();  
                        }    
                    }
                2.5.3删除
                    /**
                     * 删除
                     */
                    @Test
                    public void testRemove(){  
                        //定义对象
                        EntityManager em=null;  
                            EntityTransaction tx=null;  
                            try{  
                                //获取实体管理对象
                                em=JPAUtil.getEntityManager();
                                //获取事务对象
                                tx=em.getTransaction();
                                //开启事务
                                tx.begin();
                                //执行操作
                                Customer c1 = em.find(Customer.class, 6L);
                                em.remove(c1);
                                //提交事务
                                tx.commit(); 
                            }catch(Exception e){
                                //回滚事务
                                tx.rollback();
                                e.printStackTrace();  
                            }finally{  
                                //释放资源
                                em.close();  
                            }    
                    }
                2.5.4查询一个
                    /**
                     * 查询一个:
                     *     使用立即加载的策略
                     */
                    @Test
                    public void testGetOne(){  
                        //定义对象
                        EntityManager em=null;  
                            EntityTransaction tx=null;  
                         try{  
                                //获取实体管理对象
                                em=JPAUtil.getEntityManager();
                                //获取事务对象
                                tx=em.getTransaction();
                                //开启事务
                                tx.begin();
                                //执行操作
                                Customer c1 = em.find(Customer.class, 1L);
                                //提交事务
                                tx.commit();  
                                System.out.println(c1); //输出查询对象
                         }catch(Exception e){
                                //回滚事务
                                tx.rollback();
                                e.printStackTrace();  
                            }finally{  
                                //释放资源
                                em.close();  
                            }    
                    } 
                    
                查询实体的缓存问题
                @Test
                    public void testGetOne(){  
                        //定义对象
                        EntityManager em=null;  
                        EntityTransaction tx=null;  
                        try{  
                            //获取实体管理对象
                            em=JPAUtil.getEntityManager();
                            //获取事务对象
                            tx=em.getTransaction();  
                            //开启事务
                            tx.begin();
                            //执行操作
                            Customer c1 = em.find(Customer.class, 1L);
                            Customer c2 = em.find(Customer.class, 1L);
                            System.out.println(c1 == c2);//输出结果是true,EntityManager也有缓存
                            //提交事务
                            tx.commit();  
                            System.out.println(c1);
                        }catch(Exception e){
                            //回滚事务
                            tx.rollback();
                            e.printStackTrace();  
                        }finally{  
                            //释放资源
                            em.close();  
                        }    
                    }

                延迟加载策略的方法:
                    /**
                     * 查询一个:
                     *     使用延迟加载策略
                     */
                    @Test
                    public void testLoadOne(){  
                        //定义对象
                        EntityManager em=null;  
                        EntityTransaction tx=null;  
                        try{  
                            //获取实体管理对象
                            em=JPAUtil.getEntityManager();
                            //获取事务对象
                            tx=em.getTransaction();
                            //开启事务
                            tx.begin();
                            //执行操作
                            Customer c1 = em.getReference(Customer.class, 1L);
                            //提交事务
                            tx.commit();  
                            System.out.println(c1);
                        }catch(Exception e){
                            //回滚事务
                            tx.rollback();
                            e.printStackTrace();  
                        }finally{  
                            //释放资源
                            em.close();  
                        }    
                    }
                2.5.5查询所有
                    /**
                     * 查询所有
                     *     涉及的对象:
                     *         Query(注意:不是Hibernate的Query)
                     *      如何获取:
                     *          使用EntityManager的createQuery(String JPQL)方法;
                     *      参数的含义
                     *          JPQL:jpa  query language
                     *          JPQL的写法:
                     *          表名使用实体类名称替代
                     *          列名使用实体类属性名称替代
                     *          不能使用*号。查询所有,需要在from关键字后面的类名上加别名
                     *          例如: select c from Customer c
                     *          查询条件可以使用?作为参数占位符。
                     *          给占位符赋值时,占位符索引位置从1开始
                     *    获取结果集的方法
                     *        getResultList():查询结果是一个List集合
                     *         getSingleResult():查询结果是一个对象
                     */
                    @Test
                    public void testFindAll(){
                        //定义对象
                        EntityManager em=null;  
                        EntityTransaction tx=null;  
                        try{  
                            //获取实体管理对象
                            em=JPAUtil.getEntityManager();
                            //获取事务对象
                            tx=em.getTransaction();
                            //开启事务
                            tx.begin();
                            //执行操作
                            Query query = em.createQuery("select c from Customer c where custName like ? ");
                            query.setParameter(1,"%学院%");
                            List list = query.getResultList();
                            //提交事务
                            tx.commit(); 
                            
                            for(Object o : list){
                                System.out.println(o);
                            }
                        }catch(Exception e){
                            //回滚事务
                            tx.rollback();
                            e.printStackTrace();  
                        }finally{  
                            //释放资源
                            em.close();  
                        }   
                    }
        
        3.1一对多关系映射
            3.1.1常用注解
            3.1.1.1@OneToMany:
            作用:
                建立一对多的关系映射
            属性:
                targetEntityClass:指定多的方的类的字节码
                mappedBy:指定从表实体类中引用主表对象的名称。
                cascade:指定要使用的级联操作
                fetch:指定是否采用延迟加载
                orphanRemoval:是否使用孤儿删除
            3.1.1.2@ManyToOne
            作用:
                建立多对一的关系
            属性:
                targetEntityClass:指定一的一方实体类字节码
                cascade:指定要使用的级联操作
                fetch:指定是否采用延迟加载
                optional:关联是否可选。如果设置为false,则必须始终存在非空关系。
            3.1.1.3@JoinColumn
            作用:
                用于定义主键字段和外键字段的对应关系。
            属性:
                name:指定外键字段的名称
                referencedColumnName:指定引用主表的主键字段名称
                unique:是否唯一。默认值不唯一
                nullable:是否允许为空。默认值允许。
                insertable:是否允许插入。默认值允许。
                updatable:是否允许更新。默认值允许。
                columnDefinition:列的定义信息。
            3.1.2配置代码
            3.1.2.1客户配置
            /**
             * 客户的实体类 
             * 明确使用的注解都是JPA规范的
             * 所以导包都要导入javax.persistence包下的
             *
             */
            @Entity//表示当前类是一个实体类
            @Table(name="cst_customer")//建立当前实体类和表之间的对应关系
            public class Customer implements Serializable {
                
                @Id//表明当前私有属性是主键
                @GeneratedValue(strategy=GenerationType.IDENTITY)//指定主键的生成策略
                @Column(name="cust_id")//指定和数据库表中的cust_id列对应
                private Long custId;
                @Column(name="cust_name")//指定和数据库表中的cust_name列对应
                private String custName;
                @Column(name="cust_source")//指定和数据库表中的cust_source列对应
                private String custSource;
                @Column(name="cust_industry")//指定和数据库表中的cust_industry列对应
                private String custIndustry;
                @Column(name="cust_level")//指定和数据库表中的cust_level列对应
                private String custLevel;
                @Column(name="cust_address")//指定和数据库表中的cust_address列对应
                private String custAddress;
                @Column(name="cust_phone")//指定和数据库表中的cust_phone列对应
                private String custPhone;
                
                @OneToMany(targetEntity=LinkMan.class,mappedBy="customer")
                private Set<LinkMan> linkmans = new HashSet<LinkMan>(0);
                
                public Long getCustId() {
                    return custId;
                }
                public void setCustId(Long custId) {
                    this.custId = custId;
                }
                public String getCustName() {
                    return custName;
                }
                public void setCustName(String custName) {
                    this.custName = custName;
                }
                public String getCustSource() {
                    return custSource;
                }
                public void setCustSource(String custSource) {
                    this.custSource = custSource;
                }
                public String getCustIndustry() {
                    return custIndustry;
                }
                public void setCustIndustry(String custIndustry) {
                    this.custIndustry = custIndustry;
                }
                public String getCustLevel() {
                    return custLevel;
                }
                public void setCustLevel(String custLevel) {
                    this.custLevel = custLevel;
                }
                public String getCustAddress() {
                    return custAddress;
                }
                public void setCustAddress(String custAddress) {
                    this.custAddress = custAddress;
                }
                public String getCustPhone() {
                    return custPhone;
                }
                public void setCustPhone(String custPhone) {
                    this.custPhone = custPhone;
                }
                public Set<LinkMan> getLinkmans() {
                    return linkmans;
                }
                public void setLinkmans(Set<LinkMan> linkmans) {
                    this.linkmans = linkmans;
                }
                @Override
                public String toString() {
                    return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource
                            + ", custIndustry=" + custIndustry + ", custLevel=" + custLevel + ", custAddress=" + custAddress
                            + ", custPhone=" + custPhone + "]";
                }
            }
            3.1.2.2联系人配置
            /**
             * 联系人的实体类(数据模型)
            */
            @Entity
            @Table(name="cst_linkman")
            public class LinkMan implements Serializable {
                @Id
                @GeneratedValue(strategy=GenerationType.IDENTITY)
                @Column(name="lkm_id")
                private Long lkmId;
                @Column(name="lkm_name")
                private String lkmName;
                @Column(name="lkm_gender")
                private String lkmGender;
                @Column(name="lkm_phone")
                private String lkmPhone;
                @Column(name="lkm_mobile")
                private String lkmMobile;
                @Column(name="lkm_email")
                private String lkmEmail;
                @Column(name="lkm_position")
                private String lkmPosition;
                @Column(name="lkm_memo")
                private String lkmMemo;

                //多对一关系映射:多个联系人对应客户
                @ManyToOne(targetEntity=Customer.class)
                @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
                private Customer customer;//用它的主键,对应联系人表中的外键
                
                public Long getLkmId() {
                    return lkmId;
                }
                public void setLkmId(Long lkmId) {
                    this.lkmId = lkmId;
                }
                public String getLkmName() {
                    return lkmName;
                }
                public void setLkmName(String lkmName) {
                    this.lkmName = lkmName;
                }
                public String getLkmGender() {
                    return lkmGender;
                }
                public void setLkmGender(String lkmGender) {
                    this.lkmGender = lkmGender;
                }
                public String getLkmPhone() {
                    return lkmPhone;
                }
                public void setLkmPhone(String lkmPhone) {
                    this.lkmPhone = lkmPhone;
                }
                public String getLkmMobile() {
                    return lkmMobile;
                }
                public void setLkmMobile(String lkmMobile) {
                    this.lkmMobile = lkmMobile;
                }
                public String getLkmEmail() {
                    return lkmEmail;
                }
                public void setLkmEmail(String lkmEmail) {
                    this.lkmEmail = lkmEmail;
                }
                public String getLkmPosition() {
                    return lkmPosition;
                }
                public void setLkmPosition(String lkmPosition) {
                    this.lkmPosition = lkmPosition;
                }
                public String getLkmMemo() {
                    return lkmMemo;
                }
                public void setLkmMemo(String lkmMemo) {
                    this.lkmMemo = lkmMemo;
                }    
                public Customer getCustomer() {
                    return customer;
                }
                public void setCustomer(Customer customer) {
                    this.customer = customer;
                }
                @Override
                public String toString() {
                    return "LinkMan [lkmId=" + lkmId + ", lkmName=" + lkmName + ", lkmGender=" + lkmGender + ", lkmPhone="
                            + lkmPhone + ", lkmMobile=" + lkmMobile + ", lkmEmail=" + lkmEmail + ", lkmPosition=" + lkmPosition
                            + ", lkmMemo=" + lkmMemo + "]";
                }
            }
            3.2多对多关系映射
            3.2.1常用注解:
            3.2.1.1@ManyToMany
            作用:
                用于映射多对多关系
            属性:
                cascade:配置级联操作。
                fetch:配置是否采用延迟加载。
                targetEntity:配置目标的实体类。映射多对多的时候不用写。
            3.2.1.2@JoinTable
            作用:
                针对中间表的配置
            属性:
                name:配置中间表的名称
                joinColumns:中间表的外键字段关联当前实体类所对应表的主键字段                          
                inverseJoinColumn:中间表的外键字段关联对方表的主键字段
                    
            3.2.1.3@JoinColumn
            作用:
                用于定义主键字段和外键字段的对应关系。
            属性:
                name:指定外键字段的名称
                referencedColumnName:指定引用主表的主键字段名称
                unique:是否唯一。默认值不唯一
                nullable:是否允许为空。默认值允许。
                insertable:是否允许插入。默认值允许。
                updatable:是否允许更新。默认值允许。
                columnDefinition:列的定义信息。
                
            3.2.2配置代码
            3.2.2.1用户配置
            /**
             * 用户的数据模型
            */
            @Entity
            @Table(name="sys_user")
            public class SysUser implements Serializable {
                
                @Id
                @GeneratedValue(strategy=GenerationType.IDENTITY)
                @Column(name="user_id")
                private Long userId;
                @Column(name="user_code")
                private String userCode;
                @Column(name="user_name")
                private String userName;
                @Column(name="user_password")
                private String userPassword;
                @Column(name="user_state")
                private String userState;
                
                //多对多关系映射
                @ManyToMany(mappedBy="users")
                private Set<SysRole> roles = new HashSet<SysRole>(0);
                
                public Long getUserId() {
                    return userId;
                }
                public void setUserId(Long userId) {
                    this.userId = userId;
                }
                public String getUserCode() {
                    return userCode;
                }
                public void setUserCode(String userCode) {
                    this.userCode = userCode;
                }
                public String getUserName() {
                    return userName;
                }
                public void setUserName(String userName) {
                    this.userName = userName;
                }
                public String getUserPassword() {
                    return userPassword;
                }
                public void setUserPassword(String userPassword) {
                    this.userPassword = userPassword;
                }
                public String getUserState() {
                    return userState;
                }
                public void setUserState(String userState) {
                    this.userState = userState;
                }
                public Set<SysRole> getRoles() {
                    return roles;
                }
                public void setRoles(Set<SysRole> roles) {
                    this.roles = roles;
                }
                @Override
                public String toString() {
                    return "SysUser [userId=" + userId + ", userCode=" + userCode + ", userName=" + userName + ", userPassword="
                            + userPassword + ", userState=" + userState + "]";
                }
            }


            3.2.2.2角色配置
            /**
             * 角色的数据模型
            */
            @Entity
            @Table(name="sys_role")
            public class SysRole implements Serializable {
                
                @Id
                @GeneratedValue(strategy=GenerationType.IDENTITY)
                @Column(name="role_id")
                private Long roleId;
                @Column(name="role_name")
                private String roleName;
                @Column(name="role_memo")
                private String roleMemo;
                
                //多对多关系映射
                @ManyToMany
                @JoinTable(name="user_role_rel",//中间表的名称
                          //中间表user_role_rel字段关联sys_role表的主键字段role_id
                joinColumns={@JoinColumn(name="role_id",referencedColumnName="role_id")},
                          //中间表user_role_rel的字段关联sys_user表的主键user_id
                inverseJoinColumns={@JoinColumn(name="user_id",referencedColumnName="user_id")}
                )
                private Set<SysUser> users = new HashSet<SysUser>(0);
                
                
                public Long getRoleId() {
                    return roleId;
                }
                public void setRoleId(Long roleId) {
                    this.roleId = roleId;
                }
                public String getRoleName() {
                    return roleName;
                }
                public void setRoleName(String roleName) {
                    this.roleName = roleName;
                }
                public String getRoleMemo() {
                    return roleMemo;
                }
                public void setRoleMemo(String roleMemo) {
                    this.roleMemo = roleMemo;
                }
                public Set<SysUser> getUsers() {
                    return users;
                }
                public void setUsers(Set<SysUser> users) {
                    this.users = users;
                }
                @Override
                public String toString() {
                    return "SysRole [roleId=" + roleId + ", roleName=" + roleName + ", roleMemo=" + roleMemo + "]";
                }
                
                
            }


            第4章JPA的多表操作
            4.1一对多关系的增删改操作
            4.1.1保存操作
            保存原则:先保存主表,再保存从表。
                /**
                 * 保存操作
                 * 需求:
                 *     保存一个客户和一个联系人
                 * 要求:
                 *     创建一个客户对象和一个联系人对象
                 *  建立客户和联系人之间关联关系(双向一对多的关联关系)
                 *  先保存客户,再保存联系人
                 */
                @Test
                public void test1(){
                    //创建客户和联系人对象
                    Customer c = new Customer();//瞬时态
                    c.setCustName("TBD云集中心");
                    c.setCustLevel("VIP客户");
                    c.setCustSource("网络");
                    c.setCustIndustry("商业办公");
                    c.setCustAddress("昌平区北七家镇");
                    c.setCustPhone("010-84389340");
                    
                    LinkMan l = new LinkMan();//瞬时态
                    l.setLkmName("TBD联系人");
                    l.setLkmGender("male");
                    l.setLkmMobile("13811111111");
                    l.setLkmPhone("010-34785348");
                    l.setLkmEmail("[email protected]");
                    l.setLkmPosition("老师");
                    l.setLkmMemo("还行吧");

                    //建立他们的双向一对多关联关系
                    l.setCustomer(c);
                    c.getLinkmans().add(l);
                    //获取JPA操作对照
                    EntityManager em = JPAUtil.getEntityManager();
                    //获取JPA事务对象
                    EntityTransaction tx= em.getTransaction();
                        //开启事务
                        tx.begin();
                    //按照要求:先保存客户,再保存联系人(此时符合保存原则:先保存主表,再保存从表)
                    em.persist(c);
                    em.persist(l);        
                    tx.commit();
                }

            JPA注解的配置方式:不涉及多一条update语句的问题
            4.1.2删除操作
                /**
                 * 删除操作
                 *     删除从表数据:可以随时任意删除。
                 *     删除主表数据:
                 *         有从表数据引用
                 *             1、不能删除
                 *             2、如果还想删除,使用级联删除
                 *         没有从表数据引用:随便删
                 * 
                 * 在实际开发中,级联删除请慎用!(在一对多的情况下)
                 */
                @Test
                public void test3(){
                    //获取JPA操作对照
                    EntityManager em = JPAUtil.getEntityManager();
                    //获取JPA事务对象
                    EntityTransaction tx= em.getTransaction();
                        //开启事务
                        tx.begin();
                    //查询id为1的客户
                    Customer c1 = em.find(Customer.class, 2L);
                    //删除id为1的客户
                    em.remove(c1);
                    tx.commit();
                }

            级联删除的配置:
            @OneToMany(targetEntity=LinkMan.class,mappedBy="customer",cascade=CascadeType.ALL) //用CascadeType.REMOVE也可以
            private Set<LinkMan> linkmans = new HashSet<LinkMan>(0);
            4.2多对多关系的增删操作
            4.2.1保存操作
                /**
                 * 需求:
                 *     保存用户和角色
                 * 要求:
                 *     创建2个用户和3个角色
                 *     让1号用户具有1号和2号角色(双向的)
                 *     让2号用户具有2号和3号角色(双向的)
                 *  保存用户和角色
                 */
                @Test
                public void test1(){
                    //创建对象
                    SysUser u1 = new SysUser();
                    u1.setUserName("用户1");
                    SysUser u2 = new SysUser();
                    u2.setUserName("用户2");
                    
                    SysRole r1 = new SysRole();
                    r1.setRoleName("角色1");
                    SysRole r2 = new SysRole();
                    r2.setRoleName("角色2");
                    SysRole r3 = new SysRole();
                    r3.setRoleName("角色3");
                    
                    //建立关联关系
                    u1.getRoles().add(r1);
                    u1.getRoles().add(r2);
                    r1.getUsers().add(u1);
                    r2.getUsers().add(u1);
                    
                    u2.getRoles().add(r2);
                    u2.getRoles().add(r3);
                    r2.getUsers().add(u2);
                    r3.getUsers().add(u2);
                    
                    //获取JPA操作对照
                    EntityManager em = JPAUtil.getEntityManager();
                    //获取JPA事务对象
                    EntityTransaction tx= em.getTransaction();
                        //开启事务
                        tx.begin();
                    em.persist(u1);
                    em.persist(u2);
                    em.persist(r1);
                    em.persist(r2);
                    em.persist(r3);
                    tx.commit();
                }

            JPA注解的配置方式:不涉及保存失败的问题:
            4.2.2删除操作
                /**
                 * 删除操作
                 *     在多对多的删除时,双向级联删除根本不能配置
                 * 禁用
                 *    如果配了的话,如果数据之间有相互引用关系,可能会清空所有数据
                 */
                @Test
                public void test2(){
                    //获取JPA操作对照
                    EntityManager em = JPAUtil.getEntityManager();
                    //获取JPA事务对象
                    EntityTransaction tx= em.getTransaction();
                        //开启事务
                        tx.begin();
                    SysUser u1 = em.find(SysUser.class,3L);
                    em.remove(u1);
                    tx.commit();
                }

            在多对多映射配置中不能出现双向级联删除的配置,无论注解还是XML配置
        
        5.2JPA和hibernate中操作数据的方法对照
            操作    Hibernate中的方法    JPA中的方法    说明
            保存操作    save(Object entity)    persist(Object entity)    共同点:都是把临时态对象转成了持久态。
            区别:
            提供者不一样:
                save方法是hibernate提供的。
                persist方法是JPA规范提供的。
            在没有事务的情况下:
                save会去数据库中保存,hibernate提供了一个内置的事务来执行。
                persist什么都不会做。
            更新操作    update (Object entity)    merge (Object entity)    Hibernate和jpa都可以利用快照机制,不调用任何方法去更新。
            Update方法在更新时,如果遇到一级缓存已经包含了一个相同OID的对象会报错。merge则可以执行成功。
            删除操作    delete (Object entity)    remove (Object entity)    都是删除一个实体
            查询一个操作    get (Class clazz,Serializable id)
            load(Class clazz,Serializable id)    find(Class clazz,Object id)
            getReerence(Class clazz,Object id)    get和find都是立即加载。load和getReference一样都是延迟加载。
            查询所有操作    Query:使用HQL语句查询    Query:使用JPQL查询    查询语句的形式不一样。
            查询返回唯一结果操作    uniqueResult()    getSingleResult()    查询都是返回一个唯一的结果。

        JPA一对多的注解配置:
            案例:
                // ps: jpa提供的注解都在:javax.persistence包下
                @Entity
                @Table(name="cst_customer")
                public  class Customer
                {
                    @Id
                    @Column(name="cust_id")
                    @GeneratedValue(strategy=GenerationType.IDENTITY)
                    private Long cust_id; // '客户编号(主键)',
                    
                    @Column(name="cust_name")
                    private String cust_name; // '客户名称(公司名称)',
                    
                    @Column(name="cust_source")
                    private String cust_source; // '客户信息来源',
                    
                    @Column(name="cust_industry")
                    private String cust_industry; // '客户所属行业',
                    
                    @Column(name="cust_level")
                    private String cust_level; // '客户级别',
                    
                    @Column(name="cust_address")
                    private String cust_address; // '客户联系地址',
                    
                    @Column(name="cust_phone")
                    private String cust_phone; // '客户联系电话
                    
                    // 有多的一方的集合
                    /*targetEntity:对方的类型
                     * mappedBy:自己在对方里的属性名称   (mappedBy写在哪方,哪方意味着放弃外键的维护)
                     * 
                     * */
                    @OneToMany(targetEntity=LinkMan.class,mappedBy="customer",cascade=CascadeType.REMOVE)
                    private Set<LinkMan> linkmans=new HashSet();
        
                    @Entity
                    @Table(name="cst_linkman")
                    public class LinkMan 
                    {
                        @Id
                        @Column(name="lkm_id")
                        @GeneratedValue(strategy=GenerationType.IDENTITY)
                        private Long lkm_id;// '联系人编号(主键)',
                        
                        @Column(name="lkm_name")
                        private String lkm_name;// '联系人姓名',
                        
                        @Column(name="lkm_gender")
                        private String lkm_gender;// '联系人性别',
                        
                        @Column(name="lkm_phone")
                        private String lkm_phone;// '联系人办公电话',
                        
                        @Column(name="lkm_mobile")
                        private String lkm_mobile;// '联系人手机',
                        
                        @Column(name="lkm_email")
                        private String lkm_email;// '联系人邮箱',
                        
                        @Column(name="lkm_qq")
                        private String lkm_qq;// '联系人qq',
                        
                        @Column(name="lkm_position")
                        private String lkm_position;// '联系人职位',
                        
                        @Column(name="lkm_memo")
                        private String lkm_memo;// '联系人备注', 
                        
                        // 有一的一方的对象 PERSIST
                        @ManyToOne(targetEntity=Customer.class,cascade=CascadeType.PERSIST)
                        /*name:代表着外键字段的名称*/
                        /*referencedColumnName:指向的主键字段的命名称*/
                        @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
                        private Customer customer;
        
            多表对多表的注解配置:
                    @Entity
                    @Table(name="sys_user")
                    public class User 
                    {
                        @Id
                        @Column(name="user_id")
                        @GeneratedValue(strategy=GenerationType.IDENTITY)
                        private Long user_id;// '用户id',
                        @Column(name="user_code")
                        private String user_code;// '用户账号',
                        @Column(name="user_name")
                        private String user_name;// '用户名称',
                        @Column(name="user_password")
                        private String user_password;// '用户密码',
                        @Column(name="user_state")
                        private String user_state;// '1:正常,0:暂停',
                        
                        // 有角色的集合
                        /*targetEntity:对方的类型
                         * 
                         * 
                         * */
                        @ManyToMany(targetEntity=Role.class,cascade=CascadeType.ALL)
                        /*name: 中间表的名称
                        joinColumns:自己在中间表的一些配置
                        inverseJoinColumns:对方在中间表的一些配置*/
                        @JoinTable(name="sys_user_role",
                        joinColumns={
                                    /*name:自己在中间表的外键字段名称
                                    referencedColumnName:指向自己的主键字段名*/
                            @JoinColumn(name="user_id",referencedColumnName="user_id")    
                        },
                        inverseJoinColumns={
                                    /*name:对方在中间表的外键字段名称
                                    referencedColumnName:指向的对方的主键字段名称*/
                                @JoinColumn(name="role_id",referencedColumnName="role_id")
                        })
                        private Set<Role> roles=new HashSet();
        
                    @Entity
                    @Table(name="sys_role")
                    public class Role 
                    {
                        @Id
                        @Column(name="role_id")
                        @GeneratedValue(strategy=GenerationType.IDENTITY)
                        private Long role_id;// 主键id
                        
                        @Column(name="role_name")
                        private String role_name;// '角色名称',
                        @Column(name="role_memo")
                        private String role_memo;// '备注',
                        
                        // 有用户的集合
                        /*targetEntity:对方的类型
                         * mappedBy:自己在对方的属性名
                         * */
                        @ManyToMany(targetEntity=User.class,mappedBy="roles")
                        private Set<User> users=new HashSet();
        
            JPA需要在项目src下新建一个META-INF文件夹在文件夹里面配置以下信息:
                例如 :
                    <?xml version="1.0" encoding="UTF-8"?>
                    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
                    http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
                        version="2.0">
                            <!-- ps:当前根目录下必须得有一个持久化单元(至少要有一个数据库的连接信息配置) -->
                            <persistence-unit name="aaa">
                                        <!-- 数据库的连接信息 -->
                                        <properties>
                                                <!-- 必选5项 -->
                                            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
                                            <property name="hibernate.connection.url" value="jdbc:mysql:///hibernate3"></property>
                                            <property name="hibernate.connection.username" value="root"></property>
                                            <property name="hibernate.connection.password" value="1234"></property>
                                            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"></property>    
                                            
                                                <!-- 可选的 -->    
                                            <property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider"></property>
                                            <property name="hibernate.show_sql" value="true"></property>
                                            <property name="hibernate.format_sql" value="true"></property>
                                            <property name="hibernate.hbm2ddl.auto" value="update"></property>
                                                
                                        </properties>
                            </persistence-unit>
                    </persistence>
        JPA单表操作 :
            例如 :
                package cn.baidu.demo;

                public class Demo1 
                {
                    @Test //需求:保存一个客户
                    public void t1()
                    {
                        // 加载配置文件--返回一个类似Sessionfactory的对象
                        EntityManagerFactory factory = Persistence.createEntityManagerFactory("aaa");
                        // 类似session
                        EntityManager em = factory.createEntityManager();
                        // 获取事务
                        EntityTransaction tx = em.getTransaction(); // 事务未开启
                        // 开启事务
                        tx.begin();
                        
                        // 保存操作
                        Customer ct = new Customer();
                        ct.setCust_name("李冰冰");
                        em.persist(ct); // 类似save()
                        
                        
                        // 手动提交
                        tx.commit();
                        
                        // 释放资源
                        em.close();
                        
                    }
                    
                    @Test //查询1
                    public void t2()
                    {
                        EntityManagerFactory factory = Persistence.createEntityManagerFactory("aaa");
                        EntityManager em = factory.createEntityManager();
                        EntityTransaction tx = em.getTransaction();
                        tx.begin();
                        
                        // 查询
                        Customer ct = em.find(Customer.class, 1L); // 立即加载  类似get()
                        System.out.println(ct);
                        tx.commit();
                        em.close();
                    }
                    
                    @Test //查询2
                    public void t3()
                    {
                        EntityManagerFactory factory = Persistence.createEntityManagerFactory("aaa");
                        EntityManager em = factory.createEntityManager();
                        EntityTransaction tx = em.getTransaction();
                        tx.begin();
                        
                        // 查询2
                        Customer ct = em.getReference(Customer.class, 1L); //延迟加载  类似load()
                        System.out.println(ct);
                        tx.commit();
                        em.close();
                    }
                    
                    
                    @Test //修改
                    public void t4()
                    {
                        EntityManager em = JPAutils.createEntityManager();
                        EntityTransaction tx = em.getTransaction();
                        tx.begin();
                        
                        // 修改
                        Customer ct = em.find(Customer.class, 1L);
                        ct.setCust_name("rose");
                        em.merge(ct);  //类似update
                        
                        tx.commit();
                        em.close();
                    }
                    
                    @Test //修改 jpa支持一级缓存?  支持
                    public void t5()
                    {
                        EntityManager em = JPAutils.createEntityManager();
                        EntityTransaction tx = em.getTransaction();
                        tx.begin();
                        
                        // 修改
                        Customer ct = em.find(Customer.class, 1L);
                        ct.setCust_name("rose123");
                    
                        
                        tx.commit();
                        em.close();
                    }
                    
                    
                    @Test //删除 
                    public void t6()
                    {
                        EntityManager em = JPAutils.createEntityManager();
                        EntityTransaction tx = em.getTransaction();
                        tx.begin();
                        
                        //删除
                        Customer ct = em.find(Customer.class, 1L);
                        em.remove(ct);  // 类似之前的delete()
                    
                        
                        tx.commit();
                        em.close();
                    }
                    
                    
                    /// jpa的批量查询方式
                            // 类似咱们之前学习的query方式
                            // 1 qr.getResultList();        //类似之前的 qr.list()
                            // 2 hibernate对于占位符?是从0开始  jpa是从1开始
                            // 3  聚合    qr.getSingleResult();  //类似之前的  qr.uniqueResult(); 
                    
                    @Test
                    public void t7()
                    {
                        EntityManager em = JPAutils.createEntityManager();
                        EntityTransaction tx = em.getTransaction();
                        tx.begin();
                        
                        // 全查
                        Query qr = em.createQuery("from Customer");
                        List<Customer> list = qr.getResultList();  //类似之前的 qr.list()
                        for (Customer customer : list) {
                            System.out.println(customer);
                        }
                        
                        tx.commit();
                        em.close();
                    }
                    
                    
                    @Test
                    public void t8()
                    {
                        EntityManager em = JPAutils.createEntityManager();
                        EntityTransaction tx = em.getTransaction();
                        tx.begin();
                        
                        // 条件
                        Query qr = em.createQuery("from Customer where cust_name like ?");
                        qr.setParameter(1, "b%"); // 注意:hibernate对于占位符?是从0开始  jpa是从1开始
                        
                        List<Customer> list = qr.getResultList();
                        for (Customer customer : list) {
                            System.out.println(customer);
                        }
                        tx.commit();
                        em.close();
                    }
                    
                    
                    @Test
                    public void t9()
                    {
                        EntityManager em = JPAutils.createEntityManager();
                        EntityTransaction tx = em.getTransaction();
                        tx.begin();
                        
                        // 分页
                        Query qr = em.createQuery("from Customer");
                        qr.setFirstResult(1);  
                        qr.setMaxResults(3);
                        
                        List<Customer> list = qr.getResultList();
                        for (Customer customer : list) {
                            System.out.println(customer);
                        }
                        tx.commit();
                        em.close();
                    }
                    
                    
                    @Test
                    public void t10()
                    {
                        EntityManager em = JPAutils.createEntityManager();
                        EntityTransaction tx = em.getTransaction();
                        tx.begin();
                        
                        // 单列
                        Query qr = em.createQuery("select cust_name from Customer");
                        List<Object> list = qr.getResultList();
                        for (Object object : list) {
                            System.out.println(object);
                        }
                        tx.commit();
                        em.close();
                    }
                    
                    @Test
                    public void t11()
                    {
                        EntityManager em = JPAutils.createEntityManager();
                        EntityTransaction tx = em.getTransaction();
                        tx.begin();
                        
                        // 多列
                        Query qr = em.createQuery("select cust_id,cust_name from Customer");
                        List<Object[]> list = qr.getResultList();
                        for (Object[] object : list) {
                            System.out.println(Arrays.toString(object));
                        }
                        tx.commit();
                        em.close();
                    }
                    
                    @Test
                    public void t12()
                    {
                        EntityManager em = JPAutils.createEntityManager();
                        EntityTransaction tx = em.getTransaction();
                        tx.begin();
                        
                        // 投影
                        Query qr = em.createQuery("select new Customer(cust_id,cust_name) from Customer");
                        List<Customer> list = qr.getResultList();
                        for (Customer customer : list) {
                            System.out.println(customer);
                        }
                        tx.commit();
                        em.close();
                    }
                    
                    
                    @Test
                    public void t13()
                    {
                        EntityManager em = JPAutils.createEntityManager();
                        EntityTransaction tx = em.getTransaction();
                        tx.begin();
                        
                        // 排序
                        Query qr = em.createQuery("from Customer order by cust_id desc");
                        List<Customer> list = qr.getResultList();
                        for (Customer customer : list) {
                            System.out.println(customer);
                        }
                        tx.commit();
                        em.close();
                    }
                    
                    @Test
                    public void t14()
                    {
                        EntityManager em = JPAutils.createEntityManager();
                        EntityTransaction tx = em.getTransaction();
                        tx.begin();
                        
                        // 聚合
                        Query qr = em.createQuery("select avg(cust_id) from Customer");
                        Object obj = qr.getSingleResult(); 
                        System.out.println(obj);
                        tx.commit();
                        em.close();
                    }
                }

        JPA一对多表的操作 :
            /*
        一对多的操作*/
        public class Demo2 
        {
            @Test  // 保存一的客户3个联系人
            public void t1()
            {
                EntityManager em = JPAutils.createEntityManager();
                EntityTransaction tx = em.getTransaction();
                tx.begin();
                Customer ct = new Customer();
                ct.setCust_name("马总");
                LinkMan l1 = new LinkMan();
                l1.setLkm_name("大秘");
                LinkMan l2 = new LinkMan();
                l2.setLkm_name("中秘");
                LinkMan l3 = new LinkMan();
                l3.setLkm_name("小秘");
                
                // 双向关联
                ct.getLinkmans().add(l1);
                ct.getLinkmans().add(l2);
                ct.getLinkmans().add(l3);
                l1.setCustomer(ct);
                l2.setCustomer(ct);
                l3.setCustomer(ct);
                
                //保存
                em.persist(ct);
                em.persist(l1);
                em.persist(l2);
                em.persist(l3);
                tx.commit();
                em.close();
            }
            
            
            @Test  // 级联保存 (保存客户的同时把关联的联系人给保存了)
                        // jpa的注解里面  @OneToMany  添加属性cascade=CascadeType.PERSIST
            public void t2()  // 根据一的一方保存多的一方的数据(掌握)
            {
                EntityManager em = JPAutils.createEntityManager();
                EntityTransaction tx = em.getTransaction();
                tx.begin();
                Customer ct = new Customer();
                ct.setCust_name("马总");
                LinkMan l1 = new LinkMan();
                l1.setLkm_name("大秘");
                LinkMan l2 = new LinkMan();
                l2.setLkm_name("中秘");
                LinkMan l3 = new LinkMan();
                l3.setLkm_name("小秘");
                
                // 双向关联
                ct.getLinkmans().add(l1);
                ct.getLinkmans().add(l2);
                ct.getLinkmans().add(l3);
                l1.setCustomer(ct);
                l2.setCustomer(ct);
                l3.setCustomer(ct);
                
                //保存
                em.persist(ct);
                /*em.persist(l1);
                em.persist(l2);
                em.persist(l3);*/
                tx.commit();
                em.close();
            }
            
            
            @Test  // 级联保存 (保存联系人的同时把关联的客户给保存了)
            // jpa的注解里面 @ManyToOne  添加属性cascade=CascadeType.PERSIST
            public void t3() // 根据多的一方保存一的一方的数据(不常用)
            {
                EntityManager em = JPAutils.createEntityManager();
                EntityTransaction tx = em.getTransaction();
                tx.begin();
                Customer ct = new Customer();
                ct.setCust_name("马总");
                LinkMan l1 = new LinkMan();
                l1.setLkm_name("大秘");
                LinkMan l2 = new LinkMan();
                l2.setLkm_name("中秘");
                LinkMan l3 = new LinkMan();
                l3.setLkm_name("小秘");
                
                // 双向关联
                ct.getLinkmans().add(l1);
                ct.getLinkmans().add(l2);
                ct.getLinkmans().add(l3);
                l1.setCustomer(ct);
                l2.setCustomer(ct);
                l3.setCustomer(ct);
                
                //保存
                /*em.persist(ct);*/
                em.persist(l1);
                em.persist(l2);
                em.persist(l3);
                tx.commit();
                em.close();
            }
            
              
            @Test  // 普通删除
            public void  t4()
            {
                EntityManager em = JPAutils.createEntityManager();
                EntityTransaction tx = em.getTransaction();
                tx.begin();
                
                Customer ct = em.find(Customer.class, 4L);
                em.remove(ct);
                tx.commit();
                em.close();
            }
            
            
            @Test  // 级联删除
            // jpa的注解里面 @OneToMany  添加属性cascade=CascadeType.REMOVE (All)
            public void  t5()  //根据一的一方删除关联的多的一方的所有数据(掌握)
            {
                EntityManager em = JPAutils.createEntityManager();
                EntityTransaction tx = em.getTransaction();
                tx.begin();
                
                Customer ct = em.find(Customer.class, 4L);
                em.remove(ct);
                tx.commit();
                em.close();
            }
            
        }
        
        JPA多表对多表的操作 :
            package cn.baidu.demo;

        import javax.persistence.CascadeType;
        import javax.persistence.EntityManager;
        import javax.persistence.EntityTransaction;
        import javax.persistence.ManyToMany;

        import org.junit.Test;

        import cn.baidu.domain.Role;
        import cn.baidu.domain.User;
        import cn.baidu.utils.JPAutils;

        /*
        多对多的操作*/
        public class Demo3 
        {
            @Test  //普通保存  保存2个用户 3个角色
            public void t1()
            {
                EntityManager em = JPAutils.createEntityManager();
                EntityTransaction tx = em.getTransaction();
                tx.begin();
                
                User user1 = new User();
                user1.setUser_name("jack");
                User user2 = new User();
                user2.setUser_name("rose");
                
                Role r1 = new Role();
                r1.setRole_name("员工");
                Role r2 = new Role();
                r2.setRole_name("班主任");
                Role r3 = new Role();
                r3.setRole_name("助教");
                
                // 双向关联
                user1.getRoles().add(r1);
                user1.getRoles().add(r3);
                user2.getRoles().add(r1);
                user2.getRoles().add(r2);
                
                r1.getUsers().add(user1);
                r1.getUsers().add(user2);
                r2.getUsers().add(user2);
                r3.getUsers().add(user1);
                
                // 保存
                em.persist(user1);
                em.persist(user2);
                em.persist(r1);
                em.persist(r2);
                em.persist(r3);

                tx.commit();
                em.close();    
            }
            
            // jpa多对多的级联操作
                // 级联保存: 保存用户的同时把关联的角色给保存了(不用)
                    // @ManyToMany 添加cascade=cascade=CascadeType.PERSIST
            @Test
            public  void t2()
            {
                EntityManager em = JPAutils.createEntityManager();
                EntityTransaction tx = em.getTransaction();
                tx.begin();
                User user1 = new User();
                user1.setUser_name("jack");
                User user2 = new User();
                user2.setUser_name("rose");
                
                Role r1 = new Role();
                r1.setRole_name("员工");
                Role r2 = new Role();
                r2.setRole_name("班主任");
                Role r3 = new Role();
                r3.setRole_name("助教");
                
                // 双向关联
                user1.getRoles().add(r1);
                user1.getRoles().add(r3);
                user2.getRoles().add(r1);
                user2.getRoles().add(r2);
                
                r1.getUsers().add(user1);
                r1.getUsers().add(user2);
                r2.getUsers().add(user2);
                r3.getUsers().add(user1);
                
                // 保存
                em.persist(user1);
                em.persist(user2);
                /*em.persist(r1);
                em.persist(r2);
                em.persist(r3);*/
                
                tx.commit();
                em.close();
            }
            
            @Test  // 普通删除(常用)
            public void t3()
            {
                EntityManager em = JPAutils.createEntityManager();
                EntityTransaction tx = em.getTransaction();
                tx.begin();
                
                User user = em.find(User.class, 1L);
                em.remove(user);
                tx.commit();
                em.close();
            }
            
            @Test  // 级联删除(避免去使用)
            public void t4()
            {
                EntityManager em = JPAutils.createEntityManager();
                EntityTransaction tx = em.getTransaction();
                tx.begin();
                
                User user = em.find(User.class, 2L);
                em.remove(user);
                tx.commit();
                em.close();
            }
            
            
            // jpa的用户角色分配
                    // 添加角色
                    // 删除角色
                    // 修改角色
            @Test
            public void t5()
            {
                EntityManager em = JPAutils.createEntityManager();
                EntityTransaction tx = em.getTransaction();
                tx.begin();
                // 获取用户
                User user = em.find(User.class, 3L);
                // 获取班主任
                Role rl = em.find(Role.class, 6L);
                //给用户添加
                user.getRoles().add(rl);
                tx.commit();
                em.close();
            }
            
            
        }

        总结: 
    JPA的作用?
        给所有的orm框架提供了一套接口
    好处: 所有的ORM框架只要实现了这个JPA接口,用来操作数据库数据的方式和方法以及注解都一致了


    jpa的环境搭建: 在hibernate的环境基础上多加一个包--hibernate-entitymanager-5.0.7.Final.jar


    单表的映射
        @Entity  实体类
        @Table(name="cst_customer")  与表的映射
        @Id   指定OID属性
        @Column(name="cust_id") 指定映射的字段
        @GeneratedValue(strategy=GenerationType.IDENTITY)  指定主键的生成策略

    crud:
        persist()
            ----保存

        find()  : 立即加载
        getReference():延迟加载
            -----单条数据的oid查询

        merge()
            ---修改

        
        remove()
            ---删除

    
    批量查询:
          类似之前的query方式


    一对多:
        一: @OneToMany(targetEntity=LinkMan.class,mappedBy="customer")
        多: @ManyToOne(targetEntity=LinkMan.class)
            一对多的关系配置:
                @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")


    多对多:
        多(被动): @ManyToMany(targetEntity=User.class,mappedBy="roles")
        多(主动): @ManyToMany(targetEntity=Role.class)
             多对多的关系配置:
                @JoinTable(name="中间表的名称",joinColumns="自己在中间表的配置(数组)"
                inverseJoinColumns="对方在中间表的配置(数组)")


    级联:
        cascade=CascadeType.ALL  做级联保存以及级联删除
        cascade=CascadeType.PERSIST 只做级联保存
        cascade=CascadeType.REMOVE 只做级联删除

猜你喜欢

转载自www.cnblogs.com/haizai/p/11484973.html