hibernate

介紹

概述
    ORM體現(xiàn)
    是JBoss公司的產(chǎn)品
下載
    http://www.hibernate.org
    http://hibernate.org/orm/downloads/
    https://sourceforge.net/projects/hibernate/files/hibernate-orm/
    https://sourceforge.net/projects/hibernate/files/
解壓后文件夾說明
    documentation : 全部的文檔
        devguide : 開發(fā)指導.
        javadocs : api文檔.
        manual : 開發(fā)指南.
        quickstart : 快速開始.
    lib: 存放了所有的jar(第三方的、自己的).
        required : 必須要的jar.
        jpa : jpa實現(xiàn)的jar.
        optional: 可選的.
            c3p0 : 連接池(現(xiàn)在企業(yè)用得最多的連接池).
            ehcache : 緩存框架.
        proxool : 連接池.
    project : 存放了Hibernate框架的源碼、測試用例、資源文件、示例.
        project/etc : 存放了配置文件的模版.
基礎的jar包
    required + jpa + mysql數(shù)據(jù)庫連接
使用步驟:
    1.建庫、建表
    2.寫實體類
    3.映射實體類
        1.映射文件(不流行)-hibernate包中搜索*.hbm.xml。配置文件要和實體類在一個包下。
        2.使用jpa注解(流行)
    4.寫hibernate配置文件
        配置屬性 hibernate-release-4.3.11.Final\project\etc\hibernate.properties
    5.測試api

hibernate配置文件說明

參考 hibernate-distribution-3.6.0.Final\project\etc\hibernate.properties
hibernate.connection.driver_class
    指定數(shù)據(jù)庫連接參數(shù)
    com.mysql.jdbc.Driver
hibernate.connection.url
    如果數(shù)據(jù)庫不存在就建庫
    jdbc:mysql:///hib_demo?createDatabaseIfNotExist=true
hibernate.connection.username
    數(shù)據(jù)庫用戶名
hibernate.connection.password
    數(shù)據(jù)庫密碼
hibernate.dialect
    配置數(shù)據(jù)庫方言(指定使用哪一種數(shù)據(jù)庫,hibernate會根據(jù)這里指定的方言,生成符合當前數(shù)據(jù)庫語法的sql語句)
    org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql
    顯示hibernate在運行的時候生成的sql語句!
    true
hibernate.format_sql
    格式化sql
    true
hibernate.hbm2ddl.auto
    自動建表
    update
        表不存在則創(chuàng)建,如果表已經(jīng)存在就不創(chuàng)建表
    create
        先刪除表,再創(chuàng)建一個新表
    create-drop
        在創(chuàng)建SessionFactory時候建表;在執(zhí)行其close方法的時候刪除表
    validate
        驗證;檢查映射配置與表結(jié)構(gòu)是否一致,不一致報錯!更嚴格!
javax.persistence.validation.mode
    關閉java對象注解驗證!(如果新建web項目,使用javaee6.0以上版本,必須要加上這行!)
    none

基本使用代碼一

User.java
    public class User {
        private String id;
        private String name;
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
User.hbm.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
        <class name="com.shuai.domain.User" table="t_user">
            <id name="id" column="uid">
                <generator class="uuid"></generator>
            </id>
            <property name="name" column="uname"></property>
        </class>
    </hibernate-mapping>
hibernate.cfg.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
        <session-factory>
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="hibernate.connection.url">jdbc:mysql:///hib_demo?createDatabaseIfNotExist=true</property>
            <property name="hibernate.connection.username">root</property>
            <property name="hibernate.connection.password">root</property>
            <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
            <property name="hibernate.show_sql">true</property>
            <property name="hibernate.format_sql">true</property>
            <property name="hibernate.hbm2ddl.auto">update</property>
            <property name="javax.persistence.validation.mode">none</property> 
            <mapping resource="cn/itcast/entity/User.hbm.xml"/>
        </session-factory>
    </hibernate-configuration>
AppTest.java
    @Test
    public void Save() throws Exception {
        User user = new User();
        user.setName("Jack");
        //1. 創(chuàng)建配置管理器對象
        Configuration config = new Configuration();
        //2. 加載主配置文件:hibernate.cfg.xml
        config.configure();
        //3. 創(chuàng)建SessionFactory對象
        SessionFactory sf = config.buildSessionFactory();
        //4. 創(chuàng)建Session  (會話,與數(shù)據(jù)庫的連接的會話)
        Session session = sf.openSession();
        //5. 開啟事務
        Transaction tx = session.beginTransaction();
        //6. -- 執(zhí)行操作--
        session.save(user);
        //7. 提交事務/關閉
        tx.commit();
        session.close();
    }
    @Test
    public void get() throws Exception {
        Configuration config = new Configuration();
        config.configure();
        SessionFactory sf = config.buildSessionFactory();
        Session session = sf.openSession();
        Transaction tx = session.beginTransaction();
        User user = (User) session.get(User.class, 1);
        System.out.println(user);
        tx.commit();
        session.close();
    }

基本使用代碼二

User.java
    @Entity
    public class User {
        @Id
        private int id;
        private String name;
        private int age;
        //getter/setter
    }
hibernate.cfg.xml
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
        <session-factory>
            <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
            <property name="hibernate.show_sql">true</property>     
            <property name="hibernate.format_sql">true</property>   
            <property name="hibernate.hbm2ddl.auto">update</property>
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>
            <property name="hibernate.connection.username">root</property>
            <property name="hibernate.connection.password">32147</property>
            <property name="hibernate.c3p0.max_size">10</property>
            <property name="hibernate.c3p0.min_size">2</property>
            <mapping class="org.fkjava.hibernate.domain.User"/>
        </session-factory>
    </hibernate-configuration>
App.java
    public void testAdd(){
        // 第一步:創(chuàng)建Configuration配置信息對象 (加載全局的配置文件)
        Configuration configuration = new Configuration() // 默認會加載src/hibernate.properties屬性文件
                    .configure(); // 默認會加載src/hibernate.cfg.xml 
        // 第二步:創(chuàng)建服務注冊對象
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
        // 第三步:創(chuàng)建SessionFactory 
        SessionFactory sf = configuration.buildSessionFactory(serviceRegistry);
        // 第四步:創(chuàng)建Session
        Session session = sf.openSession();
        // 第五步:開啟事務,得到事務對象
        Transaction transaction = session.beginTransaction();
        // 第六步:利用Session完成所有的持久化操作
        User user = new User();
        user.setId(1);
        user.setAge(20);
        user.setName("帥哥");
        session.save(user);
        // 第七步:事務提交或回滾 commit|rollback
        transaction.commit();
        // 第八步:關閉Session、SessionFactory
        session.close();
        sf.close();
    }

API

hibernate3API
    Configuration 管理管理文件的類
        Configuration configure()
            加載主配置文件,默認加載src/hibenrate.cfg.xml 
        SessionFactory buildSessionFactory()
            創(chuàng)建session的工廠(hibernate.cfg.xml中就是session工廠的配置?。?             一個應用程序只需要一個session工廠即可!單例對象!
        SessionFactory addClass(..) 
            加載指定類的字節(jié)碼對應的映射文件!  (User.hbm.xml)
            注意:
                1.去對象所在的包下去找對應的映射文件;  
                2. 映射文件必須是*.hbm.xml后綴
                3. 測試使用才去使用,比較方便!
    SessionFactory session工廠
        Session openSession()   
            創(chuàng)建新的session對象
        Session getCurrentSession()
            創(chuàng)建session  (使用時候需要配置hibernate.cfg.xml)
            (<property name="hibernate.current_session_context_class">thread</property>)
    Session   與數(shù)據(jù)庫連接的會話!(里面維護了一個數(shù)據(jù)庫連接)
        hibernate中操作數(shù)據(jù)庫就是通過session對象操作的!
        Serializable  save(obj);    
            保存對象  【主鍵自增長,就不用設置主鍵,設置了也沒有!】
        void delete(obj);           
            刪除對象  【對象的主鍵一定要存在】
        void update(obj);           
            修改對象  【對象的主鍵一定要存在】
        void saveOrUpdate(obj);     
            保存或修改【有設置主鍵執(zhí)行更新,如果設置主鍵不存在就報錯!  沒有設置主鍵就保存!】
        Object get(Class clazz,Serializable id);
            主鍵查詢
        查詢方式
            1.寫HQL語句查詢【面向?qū)ο蟛樵儭?                hibernate query language    
                hibernate提供的面向?qū)ο蟮牟樵冋Z句
                實現(xiàn):session.createQuery(arg0);
            2.Criteria查詢【面向?qū)ο蟛樵儭?                session.createCriteria(sql);
            3.本地sql查詢【支持原生態(tài)的sql語句查詢】
                session.createSQLQuery(sql)
    Transaction 事務
         hibernate要求對數(shù)據(jù)庫數(shù)據(jù)的操作必須在一個事務環(huán)境內(nèi)進行!
    Query
        List list();  
            執(zhí)行的查詢的hql
        int executeUpdate();  
            執(zhí)行的更新的hql
hibernate4
    Configuration
        專門負責加載全局的配置文件,產(chǎn)生SessionFactory.
    ServiceRegistry
    SessionFactory
        它是當前數(shù)據(jù)庫在內(nèi)存中鏡像。一個SessionFactory對應一個數(shù)據(jù)庫,所以SessionFactory只能有一個,
        當應用一啟動就獲取SessionFactory,當應用關閉時才關閉SessionFactory.
        它是線程安全的.
        它是創(chuàng)建Session的工廠。
        它底層封裝了數(shù)據(jù)源(連接池)。
        它還有一個可選的二級緩存. (默認是關閉的).
    Session
        概述
            它是應用程序與持久層進行交互的單線程對象。
            它是線程不安全。
            它存活的時間比較短.(因為它底層封裝得是Connection,用完就要關閉).
            它是事務工廠.
            有一個必須開啟的一級緩存. (一級緩存永遠都是開啟的).
        方法
            contains(object);
                判斷一級緩存中是否包含這個對象,true為持久化狀態(tài)
    Transaction
        Hibernate事務對象.
        JDBC事務(局部事務) : 只能對一個數(shù)據(jù)庫中的表做事務. (web容器) tomcat jetty
        JTA事務(全局事務、分布式事務) : 可以對多個數(shù)據(jù)庫中的表做事務.(EJB容器)
            WebSphere(IBM)、WebLogic(Oracle)、JBoss(jboss)
    ConnectionProvider
        數(shù)據(jù)庫連接的提供者.
        一般指得是數(shù)據(jù)源DataSource(連接池).

持久化類的狀態(tài)

Transient 瞬態(tài)
    new 持久化類(),剛new出來的,從來沒有與Session關聯(lián)過.
Persistent 持久化狀態(tài)
    正在被Session管理中。調(diào)用Session的方法對它進行操作過,這個時候Session沒有關閉.
    該對象在Session一級緩存中. (在內(nèi)存中).
    如果你調(diào)用持久化狀態(tài)對象的set方法,它會影響數(shù)據(jù)庫表中的數(shù)據(jù).
    你對持久化狀態(tài)對象做的修改,會同步到底層的數(shù)據(jù)庫表中,它不是立即同步到底層的數(shù)據(jù)庫,默認是在事務提交時才同步。
Detached 脫管狀態(tài)
    脫離了Session的管理,曾經(jīng)被Session管理過,現(xiàn)在沒被Session管理。

Hibernate的CRUD操作

Hibernate4添加:
    a. Serializable id = session.save();
       User user = new User(); // 瞬態(tài)
       user.setXxx();
       session.save(user); // user --> 持久化狀態(tài)
    b. void session.persist();
       User user = new User(); // 瞬態(tài)
       user.setXxx();
       session.persist(user); // user --> 持久化狀態(tài)
    c. session.saveOrUpdate(); // 添加與修改
       User user = new User(); // 瞬態(tài)
       user.setXxx(); // 不要設置主鍵列對應的屬性.
       void = session.saveOrUpdate(user); // user --> 持久化狀態(tài)
    d. session.merge(); // 混合集成了添加與修改.
       User user = new User(); // 瞬態(tài)
       user.setXxx(); // 不要設置主鍵列對應的屬性.
       User u = session.merge(user); // user --> 瞬態(tài),u --> 持久化狀態(tài)
    注意:
        save()與persist()區(qū)別
            1.save方法有返回值,它返回的是主鍵id。
              persist沒有返回值,需要通過對象的getId來獲取
            2.save方法會立即往數(shù)據(jù)庫表中插入數(shù)據(jù)
              persist方法會延遲往數(shù)據(jù)庫表中插入數(shù)據(jù)(跟事務是否開啟有關)
              在事務開啟之后執(zhí)行這兩個方法做添加都會立即生成sql語句
Hibernate4根據(jù)主鍵查詢:
    session.get(): 根據(jù)主鍵id查詢
        User user = (User)session.get(User.class, 1); // user : 持久化狀態(tài)
        立即從數(shù)據(jù)庫表查詢數(shù)據(jù),返回對象.
    session.load(): 根據(jù)主鍵id查詢
        User user = (User)session.load(User.class, 1); // user : 持久化狀態(tài)
        延遲從數(shù)據(jù)庫表查詢數(shù)據(jù),一開始返回代理對象,當你真正要用到它的屬性時,
        才會生成查詢語句到數(shù)據(jù)庫表中查詢數(shù)據(jù)。
        當你要用到它的時候,要保證Session不能關閉。
Hibernate4修改:
    持久化狀態(tài)下:
        User user = (User)session.get(User.class, 1); // user : 持久化狀態(tài)
        user.setXxx();
    脫管狀態(tài)下:
        User u = new User(); // 瞬態(tài)
        u.setId(1); // 脫管
        session.update(u); // u --> 持久化狀態(tài)
        session.saveOrUpdate(u);  // u --> 持久化狀態(tài)
        User user = session.merge(u);  // u --> 脫管 user --> 持久化狀態(tài)
Hibernate4刪除:
    持久化狀態(tài)下:
        User user = (User)session.get(User.class, 1); // user : 持久化狀態(tài)
        session.delete(user); // user --> 瞬態(tài)
    脫管狀態(tài)下:
        User u = new User(); // u  -> 瞬態(tài)
        u.setId(3); //  u  -> 脫管
        session.delete(u); // 瞬態(tài)

注解實現(xiàn)方式詳細介紹

注解作用
    將持久化類轉(zhuǎn)換成表的相關信息.(表名,索引,唯一約束,列名的相關信息、關聯(lián))
基礎映射(注解加在持久化類上)
    entity/table/DynamicInsert/DynamicUpdate/SelectBeforeUpdate
主鍵映射/復合主鍵映射
    id/GeneratedValue/EmbeddedId
基本屬性映射(持久化類中屬性轉(zhuǎn)化成數(shù)據(jù)庫表中列的相關信息)
    Column/Lob/Temporal/Transient
集合屬性映射
    
關聯(lián)映射
繼承映射

注解

第一類
    類名上
    @Entity
        將POJO轉(zhuǎn)化成持久化類。
    @Table
        把持久化類轉(zhuǎn)化成表的相關信息
        name:指定表名
        schema :指定將數(shù)據(jù)表存入哪個數(shù)據(jù)庫,schema或者catalog只能指定一個.
        catalog:指定將數(shù)據(jù)表存入哪個數(shù)據(jù)庫,schema或者catalog只能指定一個.
        indexes: 用于指定表的引索列
            @Index(columnList="數(shù)據(jù)表中的列名", name="索引名")
            indexes={@Index(), @Index()}
        uniqueConstraints:用于指定唯一約束
            @uniqueConstraint(columnNames={"列名","列名"}, name="唯一約束名")
    @DynamicInsert
        動態(tài)插入,根據(jù)持久化對象的屬性是否有值明確生成insert語句。
    @DynamicUpdate
        動態(tài)修改,它會判斷持久化對象中屬性,哪些屬性值發(fā)生了改變就會生成update的語句。(持久化狀態(tài)下做修改)
    @SelectBeforeUpdate
        修改之前先查詢,查詢得到持久化對象再與脫管狀態(tài)下的對象進行比較,哪些屬性值發(fā)生了改變就會生成update的語句。(脫管狀態(tài)下做修改)
第二類
    主鍵上
    @Id
        主鍵列
    @GeneratedValue(strategy=GenerationType.AUTO)
        指定了主鍵自增長策略
        GenerationType.IDENTITY: 適宜MySQL、SqlServer有自增長列的數(shù)據(jù)庫。
        GenerationType.SEQUENCE:適宜Oracle這種沒有自增長有sequence的數(shù)據(jù)庫。
        GenerationType.AUTO:讓Hibernate根據(jù)數(shù)據(jù)庫方言自動選擇主鍵生成策略。
        GenerationType.TABLE: 適宜所有的數(shù)據(jù)庫,因為它會單獨生成一張表來維護主鍵生成。
    @Embedded
        復合主鍵
    @AttributeOverrides
        指定復合主鍵中的列表
        @AttributeOverrides({@AttributeOverride(name="firstName", column=@Column(name="F_NAME")),@AttributeOverride(name="lastName", column=@Column(name="L_NAME"))})
第三類
    普通屬性上
    @Column
        持久化類中屬性轉(zhuǎn)化成數(shù)據(jù)庫表中列的相關信息
        name:指定列名。
        length: 該列支持的長度。
        precision:有效的總位數(shù)。(BigDecimal類型才有效)
        scale:小數(shù)點的位數(shù)。(BigDecimal類型才有效)
        unique: 唯一約束。
        nullable:非空約束。
        insertable:是否允許插入true:允許 false: 不允許。
        updatable:是否允許修改true:允許 false: 不允許。
        columnDefinition :指定列的定義。columnDefinition="int(11) not null default 20"
    @Lob
        映射大的二進制數(shù)或者文本
    @Temporal
        修飾日期類型Date
        TemporalType.DATE : yyyy-MM-dd
        TemporalType.TIME : HH:mm:ss
        TemporalType.TIMESTAMP : yyyy-MM-dd HH:mm:ss
    @Transient
        指定不是持久化屬性
        transient關鍵字修飾不需要序列化的屬性,同時用它也能指定不是持久化的屬性。
第四類
    集合屬性上(List/Set/Map/Array)
    當持久化中有一個屬性是集合(Set、List、Map).
    集合屬性會單獨生成一張表
    定義集合屬性時面向接口,并且集合屬性需要程序員自己初始化
        private List<String> list = new ArrayList<String>();
    @ElementCollection
        指定加載策略/指定集合中的元素類型
        @ElementCollection(fetch=FetchType.LAZY,targetClass=String.class)
            fetch=FetchType.EAGER: 立即加載 / fetch=FetchType.LAZY: 延遲加載
            targetClass 集合中元素的類型
    @CollectionTable
        指定集合的表名
        @CollectionTable(name="info") 
    List集合(有序集合)
        @OrderColumn
            指定排序列
            @OrderColumn(name="o_id")
        @Embeddable
            說明此類是集合中的元素
            
    Set集合(無序集合)
        @Embeddable
        注意:
            Set集合生成表默認是沒有主鍵列的。如果想要生成主鍵列,需要為Set集合的元素類的屬性上添加非空約束!
                @Column(nullable:false)
            Set集合生成表的主鍵列:【外鍵列 + Set集合的元素列】
    Map集合(有Map的key)
        @MapKeyColumn
        @Embeddable
        注意
            Map集合生成表的主鍵列:【外鍵列 + Map的Key】
第五類
    關聯(lián)映射
    單向關聯(lián)
        一對一
            //學生表中增加一個關聯(lián)id
            @OneToOne(fetch=FetchType.LAZY,targetEntity=Teacher.class)
            @JoinColumn(name="t_id",referencedColumnName="id")
            private Teacher teacher;
        一對多
            //學生表中增加一個關聯(lián)id
            @OneToMany(fetch=FetchType.LAZY,targetEntity=Student.class,mappedBy="teacher")//延遲加載,指定關聯(lián)的持久化類,指定哪些維護關聯(lián)關系
            @JoinColumn(name="t_id",referencedColumnName="id")
            private Set<Student> students = new HashSet<Student>();
        多對一
            //學生表中增加一個關聯(lián)id
            @ManyToOne(fetch=FetchType.LAZY,targetEntity=Teacher.class)
            @JoinColumn(name="t_id",referencedColumnName="id")
            private Set<Student> students = new HashSet<Student>();
        多對多
            @ManyToMany(fetch=FetchType.LAZY,targetEntity=Teacher.class)
            @JoinTable(name="t_tea_stu",joinColumns=@JoinColumn(name="s_id",referencedColumnName="id"),inverseJoinColumns=@JoinColumn(name="t_id",referencedColumnName="id"))
            private Set<Teacher> teachers = new HashSet<Teacher>();
    雙向關聯(lián)
        一對一
            注解:@OneToOne
            @OneToOne(fetch=FetchType.LAZY,targetEntity=Student.class,mappedBy="teacher")
            private Student student;
            @OneToOne(fetch=FetchType.LAZY,targetEntity=Teacher.class)
            @JoinColumn(name="t_id",referencedColumnName="id",unique=true)
            private Teacher teacher;
            
        一對多
            一端(主表):@OneToMany
                @OneToMany(fetch=FetchType.LAZY,targetEntity=Student.class,mappedBy="teacher")//延遲加載,指定關聯(lián)的持久化類,指定哪些維護關聯(lián)關系
                private Set<Student> students = new HashSet<Student>();
            多端(從表):@ManyToOne
                生成外鍵列
                @ManyToOne(fetch=FetchType.LAZY,targetEntity=Teacher.class)//延遲加載,指定關聯(lián)的持久化類
                @JoinColumn(name="t_id",referencedColumnName="id",foreignKey=@ForeignKey(name="fk_tea_stu"))//生成外鍵列t_id,關聯(lián)Teacher類中的id
                private Teacher teacher;
            保存主表,再保存從表
            級聯(lián)級別
                @OneToMany(fetch=FetchType.LAZY,targetEntity=Student.class,mappedBy="teacher",cascade=CascadeType.REMOVE,orphanRemoval=true)
                    CascadeType.REMOVE 級聯(lián)刪除
                    orphanRemoval=true 刪除孤兒記錄
                        在不刪除老師的基礎上,把學生刪除
                以后千萬不要配置@ManyToOne(fetch=FetchType.LAZY,targetEntity=Teacher.class,cascade=CascadeType.REMOVE)
                    CascadeType.REMOVE 級聯(lián)刪除,以后千萬不要配置
        多對多
            注解
                @ManyToMany
            生成中間表來維護關聯(lián)關系
            用Set集合定義關聯(lián)屬性, set集合中的元素是關聯(lián)的持久化類
            @ManyToMany(fetch=FetchType.LAZY,targetEntity=Student.class,mappedBy="teachers")
            private Set<Student> students = new HashSet<Student>();
            @ManyToMany(fetch=FetchType.LAZY,targetEntity=Teacher.class)
            @JoinTable(name="t_tea_stu",joinColumns=@JoinColumn(name="s_id",referencedColumnName="id"),inverseJoinColumns=@JoinColumn(name="t_id",referencedColumnName="id"))
            private Set<Teacher> teachers = new HashSet<Teacher>();
第六類
    繼承映射
    第一種方式(SINGLE_TABLE):所有子類中屬性都生成到父類表中(一張表)
        @Entity @Table(name="parent")
        @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
        @DiscriminatorColumn(name="DC", discriminatorType=DiscriminatorType.INTEGER)// 辨別者列
        @DiscriminatorValue("1") // 辨別者列值
        public class Person{}
        //子類
        @Entity
        @DiscriminatorValue("2") // 辨別者列值
        public class Teacher{}
        注意:
            所有子類屬性中不能加非空約束
    第二種方式(JOINED):所有的子類與父類都會單獨生成表(子類表的中主鍵列同時也是外鍵列,它引用頂級父類表中的主鍵列).
        @Entity @Table(name="parent")
        @Inheritance(strategy=InheritanceType.JOINED)
        public class Person{}
        //子類
        @Entity @Table(name="teacher")
        public class Teacher{}
        注意:查詢時會出現(xiàn)很多join語句
    第三種方式(TABLE_PER_CLASS):所有的子類與父類都會單獨生成表,子類會把父類中的屬性繼承過來生成在自己的表中。
        @Entity @Table(name="parent")
        @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
        public class Person{}
        //子類
        @Entity @Table(name="teacher")
        public class Teacher{}
        注意:
            這種策略主鍵不能用自增長
            查詢時會出現(xiàn)union運算

映射文件說明

hibernate-mapping 根元素
    package 
        指定包名,如果沒有指定,本文件出現(xiàn)的所有實體類必須帶上完整包名.如果指定,就可以不帶完整包名。
    auto-import
        默認為true 自動導入,在進行hql查詢的時候不用寫包名!
         如果設置為false,在hql查詢的時候需要指定包名,如:session.createQuery("from cn.itcast.entity.User");
    schema
        庫名
class 類映射一個表
    name 類名,是否指定完整路徑看package
    table 表名
id 主鍵映射
    name 屬性名
    column 表字段名,不寫也可以
generator 主鍵策略
    native 自增長(根據(jù)底層數(shù)據(jù)庫的能力選擇 identity、sequence )
    identity  MySql中自增長的方式
    sequence  Oracle中以序列的方式實現(xiàn)自增長!
    increment  也是自增長但不能處理并發(fā)問題!
    assigned  手動指定主鍵的值
    uuid       uuid值作為主鍵
    foreign  外鍵策略(一對一映射時候用到)
property 其它字段映射
    name 屬性名
    column 表字段名,不寫也可以。如果字段是數(shù)據(jù)的關鍵字使用反引號 `desc`
    length 指定字符類型的長度,默認255
    type 指定字段類型
        hibernate支持的類型默認都是小寫 
            string/java.lang.String
            date/timestamp/ 如果屬性是java.util.Date類型,字段映射沒有指定類型,默認是datetime類型
    unique
        唯一約束
    not-null
        不能為空約束

代碼方式建表

加載hibernate.cfg.xml
    Configuration cfg = new Configuration().configure();
工具類
    SchemaExport export = new SchemaExport(cfg);
建表-參數(shù)1:是否打印生成的sql到控制臺-參數(shù)2:是否執(zhí)行生成的sql
    export.create(true, true);

查詢方式

get主鍵查詢
    User user = (User) session.get(User.class, 1);
    立即從數(shù)據(jù)庫表中查詢數(shù)據(jù)
load對象導航查詢(懶加載查詢)
    user = (User) session.load(User.class, 1);
    延遲從數(shù)據(jù)庫表查詢數(shù)據(jù),一開始返回一個代理對象,當真正用到屬性的時候,再到數(shù)據(jù)庫表中查詢
    注意:用它時保證session不要被關閉
Hql查詢 
    Hibernate Query Language 
    Hibernate查詢語句 
    步驟:
        獲得Session
        寫hql語句
        查詢數(shù)據(jù)庫獲得Query對象
        如果有占位符,就需要對占位符賦值 query.setParameter();
            如果需要分頁limit賦值 query.setFirstResult(start); query.setMaxResults(size);
        獲取查詢查詢結(jié)果
            如果本次查詢有多條記錄返回:query.list();
            如果本次查詢只有一條記錄返回:query.uniqueResult();
    from字句
        List<Student> students = session.createQuery("from Student").list();
        List<Student> students = session.createQuery("from Student as stu").list();
        List<Student> students = session.createQuery("from Student stu").list();
        User user =(User) session.createQuery("from User where id=1").uniqueResult();
    select字句
        List<Student> students = session.createQuery("select s from Student as s").list();
        List<String> names = session.createQuery("select s.name from Student s").list();
        List<Object[]> lists = session.createQuery("select s.name,s.age from Student s").list();
        List<Object[]> lists = session.createQuery("select name,age from Student").list();
    分頁
        Query query = session.createQuery("select s from Student s");
        query.setFirstResult(0);
        query.setMaxResults(5);
        List<Student> students = query.list();
    select new 字句
        可以改變List集合中存放什么
        List<Map<String,Object>> list = session.createQuery("select new map(s.name,s.age) from Student s").list();
        List<List<Object>> list = session.createQuery("select new list(s.name,s.age) from Student s").list();
        List<User> list = session.createQuery("select new com.shuai.domain.User(name,age) from Student").list();
    關聯(lián)(持久化類)與連接(數(shù)據(jù)庫表)
        隱式關聯(lián)(不需要寫join語句)
            查詢時,關聯(lián)的屬性是一個持久化類。
            List<Student> students = session.createQuery("select s from Student s where s.teacher.id=?").setParameter(0,1).list();
        顯示關聯(lián)(需要寫join語句)
            查詢時,關聯(lián)屬性是一個Set集合
            Teacher t = (Teacher)session.createQuery("select t from Teacher t inner join t.students where t.students.id=?").setParameter(1,1).uniqueResult();
        抓取連接(查詢延遲的屬性)
            查詢時,關聯(lián)屬性配置了延遲加載的,但本次查詢要查詢出來 join fetch關聯(lián)的屬性
            List<Student> students = session.createQuery("select s from Student s join fetch s.teacher").list();
    排序 order by
        List<Student> students = session.createQuery("select s from Student s order by s.age asc").list();
    分組 group by
        List<Object[]> list = session.createQuery("select count(s),s.teacher.name from Student s group by s.teacher.name").list();
    分組過濾 having
        List<Object[]> list = session.createQuery("select count(s),avg(s.score),sum(s.score),s.teacher.name from Student s group by s.teacher.name having s.teacher.id=?").setParameter(0,1).list();
    聚合函數(shù) count/sum/max/min/avg
        count
            Long count = (Long)session.createQuery("select count(*) from Student").uniqueResult();
        sum
            Double sum = (Double)session.createQuery("select sum(score) from Student").uniqueResult();
        max
            Float max = (Float)session.createQuery("select max(score) from Student").uniqueResult();
        min
            Float min = (Float)session.createQuery("select min(score) from Student").uniqueResult();
        avg
            Float avg = (Float)session.createQuery("select avg(score) from Student").uniqueResult();
    where字句部分(查詢過濾部分)
        Hibernate的where子句部分能支持的運算符,表達式、函數(shù)特別多,用法與sql語句是一樣的
        常用的表達式、運算符、函數(shù)
            =、<、<=、>、>=、!=、and、or、distinct、between...and 、like、concat()、is null, is not null, is empty, is not empty、second(...),minute(...), hour(...), day(...), month(...)
        支持EJB-QL 3.0的函數(shù)
            trim(), lower(), upper(), length(), abs(), sqrt(), bit_length(), mod()
        支持操作集合屬性的函數(shù)
            size()|size, minelement(), maxelement(), minindex(), maxindex()
        使用
            List<Student> students = session.createQuery("select s from Student s where s.name like ?8").setParameter("9","%小%").list();
            List<Student> students = session.createQuery("select s from Student s where s.name like concat('%',?2,"%")").setParameter("2","小").list();
            List<Student> students = session.createQuery("select s from Student s where s.name is not null").list();
            List<Student> students = session.createQuery("select s from Student s where trim(s.name) like ?").setParameter(0,"%帥%").list();
            List<Student> students = session.createQuery("select s from Student s where length(s.name) = ?").setParameter(0,"%帥%").list();
            List<Student> students = session.createQuery("select s from Student s where sqrt(s.id)=?").setParameter(0,1.0d).list();
            List<Student> students = session.createQuery("select s from Student s where bit_length(s.name)=?").setParameter(0,32L).list();
            List<Student> students = session.createQuery("select s from Student s where mod(s.id,?)=?").setParameter(0,2).setParameter(1,0).list();
            List<Order> orders = session.createQuery("select o from Order o where size(o.orderItems) =?").setParameter(0,3).list();
            List<Order> orders = session.createQuery("select o from Order o where minelement(o.orderItems) =?").setParameter(0,100).list();
            List<Order> orders = session.createQuery("select o from Order o where maxelement(o.orderItems) =?").setParameter(0,100).list();
            List<Order> orders = session.createQuery("select o from Order o where maxindex(o.orderItems) =?").setParameter(0,1).list();
            List<Order> orders = session.createQuery("select o from Order o where minindex(o.orderItems) =?").setParameter(0,1).list();
    子查詢
        hibernate的子查詢與SQL語句的中子查詢一樣,子查詢部分放在in、not in里面
        使用
            List<Student> students = session.createQuery("select s from Student as s where s.id in(select t.id from Teacher t)").list();
    多態(tài)查詢
        當你的持久化類存在繼承關系時,你查詢父類時,它會把父類所有的對象查詢出來,而且也會把所有子類對象查詢出來。
        使用
            List<Object> lists = session.createQuery("from java.lang.Object").list();
    命名查詢
        把所有hql語句寫在一個單獨的配置文件中
        一般在實際的項目中用得比較多,它會把比較復雜的hql語句寫在一個單獨的配置文件中
        方便以后對hql語句進行優(yōu)化,也方便統(tǒng)一管理
        第一種方式
            1.創(chuàng)建xxx.hbm.xml
                <?xml version="1.0" encoding="utf-8"?>
                <!DOCTYPE hibernate-mapping PUBLIC 
                    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
                <hibernate-mapping>
                    <query name="hql_1">select s from Student s where s.name like ?</query>
                </hibernate-mapping>
            2.在hibernate.cfg.xml文件中配置xxx.hbm.xml
                <mapping resource="com/shuai/domain/xxx.hbm.xml"/>
            3.使用
                List<Student> students = session.getNamedQuery("hql_1").setParameter(0, "%小%").list();
        第二種方式
            1.在持久化類上加注解
                @NamedQuery(name="hql_1", query="select s from Student s where s.name like ?");
                public class Student{}
            2.使用
                List<Student> students = session.getNamedQuery("hql_1").setParameter(0, "%小%").list();
Criteria查詢
    說明
        完全面向?qū)ο蟮?,不需要寫任可查詢語句
    查詢步驟
        1.獲取Session
        2.Criteria criteria = session.createCriteria(持久化類)
        3.如果需要分頁查詢就需要為limit ?,? 這兩個問號賦值
            第一個問號:criteria.setFirstResult(start);
            第二個問號:criteria.setMaxResults(size);
        4.獲取查詢查詢結(jié)果
            如果本次查詢有多條記錄返回:criteria.list();
            如果本次查詢只有一條記錄返回:criteria.uniqueResult();
    API
        add(Criterion criterion)
            添加查詢條件.Criterion : 代表一個查詢條件.
            Restrictions 工具類,專門負責生成查詢條件對象,它把where部分都改成了靜態(tài)方法。
            Property工具類,專門負責生成查詢條件對象.
        addOrder(Order order)
            添加排序
            Order.asc("屬性名") | Order.desc("屬性名")
            Property.forName("age").asc()|Property.forName("age").desc()
        setProjection(Projection projection)
            查詢哪些列
        createAlias(String associationPath, String alias)
            創(chuàng)建關聯(lián)查詢
            用它創(chuàng)建出來的關聯(lián)查詢,添加查詢條件時,如果不加別名,它是為目標持久類添加查詢條件.
        createCriteria(String associationPath)
            創(chuàng)建關聯(lián)查詢
            用它創(chuàng)建出來的關聯(lián)查詢,添加查詢條件時,它是為關聯(lián)的持久化類添加查詢條件.
        setFetchMode(String associationPath, FetchMode mode)
            抓取連接(join fetch)
            FetchMode: 抓取模式
                FetchMode.JOIN     FetchMode.EAGER 立即查詢
                FetchMode.SELECT   FetchMode.LAZY  延遲查詢
        DetachedCriteria.
            離線查詢
            用它就可以定義一條查詢語句.
            用得時候需要與Session關聯(lián)起來.
            離線查詢的主要作用就是為了做子查詢. in 、not in(離線查詢對象)
    使用
        List<Student> students = session.createCriteria(Student.class).list();
        List<Student> students = session.createCriteria("com.shuai.domain.Student").list();
        List<Student> students = session.createCriteria(Student.class).add(Restrictions.like("name","%帥%")).list();
        List<Student> students = session.createCriteria(Student.class).add(Restrictions.like("name","%帥%")).add(Restrictions.between("age",20,30)).list();
        List<Student> students = session.createCriteria(Student.class).add(Property.forName("name").like("%帥%")).list();
        List<Student> students = session.createCriteria(Student.class).add(Property.forName("age").between(20,30)).list();
        List<Student> students = session.createCriteria(Student.class).add(Restrictions.sqlRestriction("length(name)=4")).list();
        List<Student> students = session.createCriteria(Student.class).addOrder(Order.asc("age")).list();
        List<Student> students = session.createCriteria(Student.class).addOrder(Property.forName("age").asc()).list();
        List<String> names = session.createCriteria(Student.class).setProjection(Projections.property("name")).list();
        ProjectionList pl = Projections.projectionList();
        pl.add(Projections.property("name"));
        pl.add(Projections.property("age"));
        List<Object[]> names = session.createCriteria(Student.class).setProjection(pl).list();
        Object res = session.createCriteria(Student.class).setProjection(Projections.rowCount()).uniqueResult();
        Object res = session.createCriteria(Student.class).setProjection(Projections.avg("score")).uniqueResult();
        Object res = session.createCriteria(Student.class).setProjection(Projections.max("score")).uniqueResult();
        List<Object[]> lists = session.createCriteria(Student.class).setProjection(Projections.projectionList().add(Projections.rowCount()).add(Projections.property("teacher.id")).add(Projections.groupProperty("teacher.id"))).list();
        List<Student> students = session.createCriteria(Student.class).createAlias("teacher","t").add(Restrictions.eq("t.id",1)).list();
        List<Student> students = session.createCriteria(Student.class).createCriteria("teacher").add(Restrictions.eq("t.id",1)).list();
        List<Student> students = session.createCriteria(Student.class).createAlias("teacher","t").add(Restrictions.gt("age",100)).add(Restrictions.eq("t.id",1)).list();
        List<Student> students = session.createCriteria(Student.class).add(Restrictions.gt("age",100)).createCriteria("teacher").add(Restrictions.eq("id",1)).list();
        List<Student> students = session.createCriteria(Student.class).setFetchMode("teacher",FetchMode.JOIN).list();
        DetachedCriteria dc = DetachedCriteria.forClass(Student.class);
        List<Student> students = dc.getExecutableCriteria(session).list();
        DetachedCriteria dc = DetachedCriteria.forClass(Teacher.class);
        dc.setProjection(Projections.property("id"));
        List<Student> students = session.createCriteria(Student.class).add(Property.forName("id").in(dc)).list();
本地sql查詢
    說明
        Native Sql Query原生的sql查詢
        要求寫sql語句
        SQLQuery 是 Query的子類
    步驟
        1.獲取Session
        2.寫sql語句
        3.SQLQuery sqlquery = session.createSQLQuery(sql);
        4.如果hql語句中有占位符,就需要為占位符賦值. sqlquery.setParameter("索引號", "值");
            如果需要分頁查詢就需要為limit ?,? 這兩個問號賦值
            第一個問號:sqlquery.setFirstResult((pageIndex - 1) * pageSize);
            第二個問號:sqlquery.setMaxResults(pageSize);
        5.獲取查詢查詢結(jié)果
            如果本次查詢有多條記錄返回:sqlquery.list();
            如果本次查詢只有一條記錄返回:sqlquery.uniqueResult(); 
    API
        addEntity(Class entityType)
            實體查詢
        addScalar(String columnAlias)
            標量查詢
        addJoin(String tableAlias, String path)
            關聯(lián)查詢
    使用
        List<Student> students = session.createSQLQuery("select * from student").addEntity(Student.class).list();
        List<Student> students = session.createSQLQuery("select * from student").addEntity("com.shuai.domain.Student").list();
        List<Object[]> lists = session.createSQLQuery("select s.name,s.age from student as s").list();
        List<Object[]> lists = session.createSQLQuery("select * from student as s").addScalar("s.name").addScalar("s.age").list();
        List<Object[]> lists = session.createSQLQuery("select s.*,t.* from student s,teacher t where s.id = t.id").addEntity("s",Student.class).addEntity("t",Teacher.class).addJoin("t","s.teacher").addScalar("s.name").list();
    命名查詢
        第一種方式
            用xxx.hbm.xml
            步驟
                1.提供一個配置文件(xxx.hbm.xml)
                    <?xml version="1.0" encoding="utf-8"?>
                    <!DOCTYPE hibernate-mapping PUBLIC 
                        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
                    <hibernate-mapping>
                        <sql-query name="sql_1">
                            SELECT s.*,t.* FROM stu_info AS s, tea_info AS t WHERE s.t_id = t.tea_id
                            <!-- addEntity: 實體查詢 -->
                            <return alias="s" class="com.shuai.domain.Student"></return>
                            <return alias="t" entity-name="com.shuai.domain.Teacher"></return>
                            <!-- addJoin : 關聯(lián)查詢 -->
                            <return-join alias="t" property="s.teacher"></return-join>
                            <!-- addScalar : 標量查詢 -->
                            <return-scalar column="s.stu_name"/>
                        </sql-query>
                        <sql-query name="call_proc">
                            {call query_stu(?)}
                            <return class="com.shuai.domain.Student"></return>
                        </sql-query>
                    </hibernate-mapping>
                2.在hibernate.cfg.xml文件中配置xxx.hbm.xml
                    <mapping resource="com/shuai/domain/Query.hbm.xml"/>
                3.使用
                    List<Object[]> lists = session.getNamedQuery("sql_1").list();
        第二種方式
            在持久化類上加注解
            步驟
                1.在實體類上加注解
                    @NamedNativeQuery(name="sql_2", resultSetMapping="rs", query="SELECT s.*,t.* FROM stu_info AS s, tea_info AS t WHERE s.t_id = t.tea_id")
                    @SqlResultSetMapping(name="rs", entities={@EntityResult(entityClass=Student.class), // 實體查詢
                                          @EntityResult(entityClass=Teacher.class)},
                                columns={@ColumnResult(name="s.stu_name")}) // 標量要詢
                    public class Student{}
                2.使用
                    List<Object[]> lists = session.getNamedQuery("sql_2").list();
                    List<Student> lists = session.getNamedQuery("call_proc").setParameter(0, 20).list();
    Hibernate調(diào)用存儲過程
        第一種方式:用命名查詢的方法
            List<Student> lists = session.getNamedQuery("call_proc").setParameter(0, 20).list();
        第二種方式:直接用session.createSQLQuery()調(diào)用.
            List<Student> lists = session.createSQLQuery("{call query_stu(?)}").addEntity(Student.class).setParameter(0, 20).list();

hibernate批處理

概述
    如果有10w條數(shù)據(jù)需要一次性插入到數(shù)據(jù)庫表.這個時候用Hibernate做添加的話有可能會出現(xiàn)內(nèi)存溢出
批量添加
    for(int i = 0; i < 100000; i++){
        Teacher t = new Teacher();
        session.save(t);    
        // t : 持久化狀態(tài),持久化狀態(tài)的對象是放在Session的一級緩存中,因為一級緩存是放在內(nèi)存中.(10w對象存放在內(nèi)存中)
        // 當一級緩存中的對象達到一定數(shù)量,那就把一級緩存中的對象同步到底層的數(shù)據(jù)庫,再清空一級緩存,釋放內(nèi)存
        if (i % 10 == 0){
            // 把一級緩存中的對象同步到底層的數(shù)據(jù)庫
            session.flush();
            // 清空一級緩存,釋放內(nèi)存
            session.clear();
        }
    }
    session.commit();
批量修改
    for (int i = 1; i <= 100000; i++){
        // t : 持久化狀態(tài),持久化狀態(tài)的對象是放在Session的一級緩存中,因為一級緩存是放在內(nèi)存中.(10w對象存放在內(nèi)存中)
        Teacher t = (Teacher)session.get(Teacher.class, i);
        t.setAge(28);
        // 當一級緩存中的對象達到一定數(shù)量,那就把一級緩存中的對象同步到底層的數(shù)據(jù)庫,再清空一級緩存,釋放內(nèi)存
        if (i % 10 == 0){
            // 把一級緩存中的對象同步到底層的數(shù)據(jù)庫
            session.flush();
            // 清空一級緩存,釋放內(nèi)存
            session.clear();
        }
    }
    session.commit();
批量刪除
    for (int i = 1; i <= 100000; i++){
        // t : 持久化狀態(tài),持久化狀態(tài)的對象是放在Session的一級緩存中,因為一級緩存是放在內(nèi)存中.(10w對象存放在內(nèi)存中)
        Teacher t = (Teacher)session.get(Teacher.class, i);
        session.delete(t);
        // 當一級緩存中的對象達到一定數(shù)量,那就把一級緩存中的對象同步到底層的數(shù)據(jù)庫,再清空一級緩存,釋放內(nèi)存
        if (i % 10 == 0){
            // 把一級緩存中的對象同步到底層的數(shù)據(jù)庫
            session.flush();
            // 清空一級緩存,釋放內(nèi)存
            session.clear();
        }
    }
    session.commit();

DML風格的HQL語句

概述
    DML : Data Manipulation Language (DML) the statements: INSERT, UPDATE, DELETE
    語法 :( UPDATE | DELETE ) FROM? EntityName (WHERE where_conditions)?. 
操作DML風格HQL的步驟
    獲取Session
    寫DML風格的hql語句
    Query query = session.createQuery(hql);
        如果hql語句中有占位符需要設置參數(shù)值: query.setParameter(i, "值").
    int res = query.executeUpdate();
使用
    全部修改
        String sql = "update from Teacher set age = ?";
        int res = session.createQuery(sql).setParameter(0,20).executeUpdate();
    條件修改
        String sql = "update from Teacher set age = ? where id < ?";
        int res = session.createQuery(sql).setParameter(0,20).setParameter(1,100).executeUpdate();
    條件刪除
        String sql = "delete from Teacher t where t.age = ?";
        int res = session.createQuery(sql).setParameter(0,40).executeUpdate();

hibernate數(shù)據(jù)過濾

概述
    當你做查詢時,有一個查詢條件永遠是固定的
使用數(shù)據(jù)過濾的步驟
    1.定義數(shù)據(jù)過濾
        @FilterDef()
    2.指定哪些持久類使用該數(shù)據(jù)過濾
        @Filter()
    3.開啟該數(shù)據(jù)過濾
        session.enableFilter("數(shù)據(jù)過濾的名稱").setParameter("定義的過濾字段名稱",過濾字段的值);
使用
    1.
        @FilterDef(name="ageFilter", parameters={@ParamDef(name="minAge", type="int")})
        public class Teacher{}
    2.
        @Filter(name="ageFilter", condition="age > :minAge")
        public class Student{}
    3.
        session.enableFilter("ageFilter").setParameter("minAge", 20);
        List<Student> students = session.createQuery("select t from Student t").list();

hibernate連接池

支持c3p0.
使用時配置hibernate.cfg.xml
    <property name="hibernate.c3p0.min_size">3</property>
        最小連接數(shù)
    <property name="hibernate.c3p0.max_size">6</property>
        最大連接數(shù)
    <property name="hibernate.c3p0.max_statements">100</property>
        一次執(zhí)行的最大sql命令的個數(shù)
    <property name="hibernate.c3p0.acquire_increment">2</property>
        連接不夠用一次增加多少個連接
    <property name="hibernate.c3p0.timeout">5000</property>
        連接超時時間
    <property name="hibernate.c3p0.idle_test_period">3000</property>
        連接空閑測試時間

hibernate緩存

為什么使用緩存
    減少數(shù)據(jù)庫訪問次數(shù),提高程序運行效率
一級緩存 
    session
    緩存不共享,每個session維護自己獨立的緩存區(qū),session關閉后,緩存銷毀
    特點:緩存時間短范圍小,效果不太明顯.
    跟Session相關(存放在內(nèi)存中)
    默認是開啟的
    作用:提高CUD操作的性能
    操作
        boolean contains(Object object)
            判斷Session的一級緩存中是否包含一個對象,包含的話這個對象就是持久化狀態(tài)。
        void  evict(Object object)
            從Session的一級緩存中逐出一個對象.(該對象就不是持久化狀態(tài)的對象).
        void  flush()
            將Session的一級緩存中的對象,同步到底層數(shù)據(jù)庫表中.(立即同步)
        void  clear()
            清空Session的一級緩存,所有的持久化狀態(tài)的對象都清空。(釋放內(nèi)存)
        void close()
            關閉Session,先調(diào)用flush(),再調(diào)用clear().
二級緩存
    基于sessionFactory的緩存
    二級緩存的內(nèi)容,可以給多個session訪問,二級緩存數(shù)據(jù)可以給所有的session共享.
    跟SessionFactory相關,因為SessionFactory存活的時間長。
    默認是關閉的.
    作用:提高查詢效率.
    特點:緩存資源,整個應用程序都可以使用.范圍比較大.
    使用二級緩存:
        1.需要指定哪些類需要放入二級緩存區(qū)域
        2.放入緩存的數(shù)據(jù),要符合這樣的特點,不要經(jīng)常修改
    hibernate的二級緩存是以插件的形式提供給開發(fā)程序員使用的,且有已經(jīng)實現(xiàn)好的插件.
    用的時候直接引入即可(hibernate.cfg.xml)配置.
    二級緩存中的對象存放到哪里,這個需要配置.
    一般會配置內(nèi)存中存放一些對象,超出了內(nèi)存中放存的對象個數(shù),就寫入磁盤.
    ehcache.xml (配置二級緩存對象存放的配置文件).
    HashtableCacheProvider使用步驟:
        1.hibernate.cfg.xml配置開啟二級緩存
            <property name="hibernate.cache.use_second_level_cache">true</property>
        2.hibernate.cfg.xml配置使用哪個二級緩存框架
            <property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
        3.配置指定哪些類加入緩存
            第一種配置hibernate.cfg.xml
                <class-cache usage="read-write" class="cn.shuai.domain.User"/>
                    read-only/read-write
            第二種配置User.hbm.xml
                <cache usage="read-write"/>
        4.開啟對象中的集合緩存-注意集合中的對象也要加入緩存
            <class-cache usage="read-write" class="cn.shuai.domain.Address"/>
            <collection-cache usage="read-write" collection="cn.shuai.domain.User.addresses"/>
        5.注意:
            以上配置是對get查詢方式配置的.
        6.如果需要對Hql查詢也可以讀取二級緩存,還需要配置
            <property name="hibernate.cache.use_query_cache">true</property>
        7.并且使用HQL查詢時寫法要注意
            User user =(User) session.createQuery("from User where id=1").setCacheable(true);//數(shù)據(jù)要加入二級緩存/數(shù)據(jù)從二級緩存中取
    EhCacheRegionFactory使用
        1.配置開啟二級緩存hibernate.cfg.xml文件中配置開啟二級緩存.
            <property name="hibernate.cache.use_second_level_cache">true</property>
            <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
        2.拷貝二級緩存需要的jar包
            ehcache-core-2.4.3.jar、hibernate-ehcache-4.3.8.Final.jar、slf4j-api-1.7.2.jar、slf4j-jdk14-1.7.2.jar
        3.拷貝ehcache.xml文件
            <ehcache>
                <diskStore path="F:\\ehcache"/>
                <defaultCache
                    maxElementsInMemory="10000"
                    eternal="false"
                    timeToIdleSeconds="120"
                    timeToLiveSeconds="120"
                    overflowToDisk="true"
                    />
                <cache name="shuaiCache"
                    maxElementsInMemory="10000"
                    eternal="false"
                    timeToIdleSeconds="120"
                    timeToLiveSeconds="120"
                    overflowToDisk="true"
                    />
            </ehcache>
        4.配置哪些持久化類用二級緩存
            第一種方式:hibernate.cfg.xml文件中配置
                <class-cache usage="read-write" class="com.shuai.domain.Teacher" region="shuaiCache"/>
            第二種方式:注解配置
                @Cache(usage=CacheConcurrencyStrategy.READ_WRITE,region="shuaiCache")
        5.操作二級緩存的方法
            Cache cache =  SessionFactory.getCache();
                獲取緩存對象
            boolean containsEntity(Class entityClass, Serializable identifier)
                判斷二級緩存中在是否包含一個對象
                boolean containsEntity(String entityName, Serializable identifier)
            void evictAllRegions();
                清空二級緩存中所有對象
            void evictEntity(Class entityClass, Serializable identifier)
                從二級緩存中踢出指定的對象
                void evictEntity(String entityName, Serializable identifier)
            void evictEntityRegion(Class entityClass)
                從二級緩存中踢出指定類型所有的對象
                void evictEntityRegion(String entityName)   
        6.查詢緩存(緩存的是查詢語句)
            
        7.獲取二級緩存的統(tǒng)計信息
            1.配置生成統(tǒng)計信息(hibernate.cfg.xml)
                <property name="hibernate.generate_statistics">true</property>
                <property name="hibernate.cache.use_structured_entries">true</property>
            2.獲取統(tǒng)計信息
                Statistics statistics = sessionFactory.getStatistics();
                命中的數(shù)量:statistics.getSecondLevelCacheHitCount()
                錯失的數(shù)量:statistics.getSecondLevelCacheMissCount()
        8.對象在二級緩存中用什么格式保存
            Map集合
                key:主鍵列的值
                value:緩存對象,該對象對需要緩存的對象中的數(shù)據(jù)做了封裝.
            SecondLevelCacheStatistics scs = statistics.getSecondLevelCacheStatistics("com.shuai.domain.Student");
            scs.getEntries();
查詢緩存(緩存的是查詢語句)
    概述
        默認也是關閉的
        它是在二級緩存的基礎之上
    使用步驟
        1.配置開啟查詢緩存(hibernate.cfg.xml)
            <property name="hibernate.cache.use_query_cache">true</property>
        2.在創(chuàng)建查詢時需要設置是否緩存這條語句.
            query.setCacheable(true);
            List<Student> students = session.createQuery("select s from Student s join fetch s.teacher").setCacheable(true).list();
    查詢緩存的緩存數(shù)據(jù)格式
        {"sql語句" : {"org.fkjava.hibernate.domain.Student" : [1,2,3,4,5,6],"org.fkjava.hibernate.domain.Teacher" : [1,2]}}
        注意:它要求hql語句要一致,而且hql語句中的占位符賦值也要一致,才能命中!     

Session的線程安全問題

概述
    如果是Hibernate3.1之前版本,它提供了HibernateUtil工具類可以獲取當前線程相關的Session.
    如果是Hibernate3.1之后版本,它提供了可配置的方式,讓我們把Session配置成線程相關的Session.
把Session配置成線程安全
    在hibernate.cfg.xml中配置
    <property name="hibernate.current_session_context_class">jta|thread</property>
        org.hibernate.context.internal.JTASessionContext : jta (全局事務)
        org.hibernate.context.internal.ThreadLocalSessionContext : thread (jdbc事務)
使用
    Session session = session.getCurrentSession();
    注意:
        不要調(diào)用session.close();

面向JPA編程

Hibernate4編程
    Configuration
    SessionFactory
    Session
    Transaction
    Query query = session.createQuery(hql);
    Criteria criteria = session.createCriteria();
    SQLQuery sqlquery = session.createSQLQuery(sql);
    src/hibernate.cfg.xml
JPA編程
    Persistence
    EntityManagerFactory
    EntityManager
    EntityTransaction
    Query query = entityManager.createQuery(jpql);
    Query query = entityManager.createQuery(CriteriaQuery);
    Query query = entityManager.createNativeQuery(sql);
    src/META-INF/persistence.xml
JPQL
    Java Persistence Query Language  
    java持久化查詢語言.
web項目引入jpa
    1.創(chuàng)建JPA項目
        new --> jpa --> jpa project --> jpa fact(jpa implementation type:disable library configuration)
        需要項目src中的META-INF文件夾和文件夾中的persistence.xml
        把這個文件夾拷貝到我們自己的web項目的src目錄即可。
    2.修改persistence.xml
        在hibernate-entitymanager-xxx.jar/org.hibernate.jpa/persistence_2_1.xsd文件中拷貝文件頭即可
        <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
            http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
          version="2.1">
        </persistence>
    3.配置持久化單元persistence-unit
        <persistence-unit name="shuaijpa" transaction-type="RESOURCE_LOCAL">
        </persistence-unit>
        name : 持久化單元名稱
        transaction-type : JTA|RESOURCE_LOCAL事務
    4.配置JPA的提供商(實現(xiàn)商)
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    5.配置持久化類
        <class>com.shuai.domain.Teacher</class>
    6.配置屬性
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <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"/>
            <property name="hibernate.connection.username" value="root"/>
            <property name="hibernate.connection.password" value="32147"/>
            <property name="hibernate.c3p0.max_size" value="10"/>
            <property name="hibernate.c3p0.min_size" value="2"/>
        </properties>
    7.使用
        public void oneTest(){
            // 第一步:創(chuàng)建EntityManagerFactory
            EntityManagerFactory emf = Persistence.createEntityManagerFactory("shuaijpa");
            // 第二步:創(chuàng)建EntityManager 
            EntityManager em = emf.createEntityManager();
            // 第三步:獲取事務
            EntityTransaction transaction = em.getTransaction();
            // 第四步:開啟事務
            transaction.begin();
            // 第五步:利用 EntityManager完成所有的持久化操作
            Teacher t = new Teacher();
            t.setName("帥哥");
            t.setDept("開發(fā)部");
            t.setAge(30);
            em.persist(t);
            // 第七步:事務提交或回滾
            transaction.commit();
            // 第八步:關閉EntityManager與EntityManagerFactory
            em.close();
            emf.close();
        }
增加
    第一種方式
        Teacher t = new Teacher(); // 瞬態(tài)
        t.setAge(20);
        t.setName("帥哥");
        t.setDept("開發(fā)部");
        t.setJob("項目經(jīng)理");
        em.persist(t); // 持久化狀態(tài)
        System.out.println(em.contains(t)); // 判斷一個對象是不是持久化狀態(tài)
    第二種方式
        Teacher t = new Teacher(); // 瞬態(tài)
        t.setAge(20);
        t.setName("帥哥");
        t.setDept("開發(fā)部");
        t.setJob("項目經(jīng)理");
        Teacher t1 = em.merge(t); // t1 持久化狀態(tài)
        System.out.println(em.contains(t1));
刪除
    Teacher t = em.find(Teacher.class, 4); // t 持久化狀態(tài)
    em.remove(t);
修改
    持久化狀態(tài)下
        Teacher t = em.find(Teacher.class, 1); // t 持久化狀態(tài)
        t.setAge(300);
    脫管狀態(tài)下
        Teacher t = new Teacher();
        t.setId(1);
        t.setAge(100);
        t.setName("admin");
        em.merge(t);
查詢
    Teacher t = em.find(Teacher.class, 1); // t 持久化狀態(tài) 
    System.out.println(em.contains(t)); // 判斷一個對象是不是持久化狀態(tài)
操作一級緩存中的方法
    boolean contains(Object object)
        判斷EntityManager的一級緩存中是否包含一個對象,包含的話這個對象就是持久化狀態(tài)。
    void  detach(Object object)
        從EntityManager的一級緩存中逐出一個對象.(該對象就不是持久化狀態(tài)的對象).
    void  flush()
        將EntityManager的一級緩存中的對象,同步到底層數(shù)據(jù)庫表中.(立即同步)
    void  clear()
        清空EntityManager的一級緩存,所有的持久化狀態(tài)的對象都清空。(釋放內(nèi)存)
    void close()
        關閉EntityManager,先調(diào)用flush(),再調(diào)用clear().
三套查詢
    第一套查詢(JPQL查詢)
        查詢步驟
            1.獲取EntityManager
            2.寫jpql語句
            3.Query query = entityManager.createQuery(jpql);
            4.如果hql語句中有占位符,就需要為占位符賦值. query.setParameter("索引號", "值");
                如果需要分頁查詢就需要為limit ?,? 這兩個問號賦值
                第一個問號:query.setFirstResult(start);
                第二個問號:query.setMaxResults(size);
            5.獲取查詢查詢結(jié)果
                如果本次查詢有多條記錄返回:query.getResultList();
                如果本次查詢只有一條記錄返回:query.getsingleResult();
        使用
            List<Student> lists = em.createQuery("select s from Student as s", Student.class).getResultList();
            List<Student> lists = em.createQuery("from Student", Student.class).getResultList();
            List<Map<String, Object>> lists = em.createQuery("select new map(name as name, age as age) from Student").getResultList();
            List<Student> lists = em.createQuery("from Student", Student.class).setFirstResult(start).setMaxResults(size).getResultList();
        命名查詢
            @NamedQuery(name="query_1", query="select s from Student s join fetch s.teacher")
            public class Teacher {}
            List<Student> lists = em.createNamedQuery("query_1").getResultList();
    第二套查詢(sql查詢)
        查詢步驟
            1.獲取EntityManager.
            2.寫sql語句.
            3.查詢
                Query query = createNativeQuery(String sqlString); // 查詢多列
                Query query = createNativeQuery(String sqlString, Class resultClass); // 實體查詢
                Query query = createNativeQuery(String sqlString, String resultSetMapping); // 關聯(lián)查詢
            4.如果hql語句中有占位符,就需要為占位符賦值. query.setParameter("索引號", "值");
                如果需要分頁查詢就需要為limit ?,? 這兩個問號賦值
                第一個問號:query.setFirstResult((pageIndex - 1) * pageSize);
                第二個問號:query.setMaxResults(pageSize);
            5.獲取查詢查詢結(jié)果:
                如果本次查詢有多條記錄返回:query.getResultList();
                如果本次查詢只有一條記錄返回:query.getsingleResult();
        使用
            List<Student> lists = em.createNativeQuery("select * from stu_info", Student.class).getResultList();
            List<Object[]> lists = em.createNativeQuery("select * from stu_info").getResultList();
            List<Object[]> lists = em.createNativeQuery("select s.*, t.* from stu_info as s, tea_info as t where s.t_id = t.tea_id", "rs").getResultList();
            @SqlResultSetMapping(name="rs" , entities={@EntityResult(entityClass=Student.class),@EntityResult(entityClass=Teacher.class)},columns={@ColumnResult(name="s.stu_name")})
            public class Student {}
    第三套查詢(CriteriaQuery查詢)
        查詢步驟
            1.獲取EntityManager.
            2.Query query = entityManager.createQuery(CriteriaQuery);
            3.如果需要分頁查詢就需要為limit ?,? 這兩個問號賦值
                第一個問號:query.setFirstResult(start);
                第二個問號:query.setMaxResults(size);
            4.獲取查詢查詢結(jié)果:
                如果本次查詢有多條記錄返回:query.getResultList();
                如果本次查詢只有一條記錄返回:query.getsingleResult();
        API
            CriteriaBuilder
                構(gòu)建查詢對象的類.
                構(gòu)建CriteriaQuery
                生成查詢條件
                生成排序
                生成聚集函數(shù)
            CriteriaQuery 
                查詢對象類
                Root from(Class<X> entityClass) : 指定查詢哪個持久化類.
                groupBy(Expression<?>... grouping) : 分組
                multiselect(Selection<?>... selections) : 查詢多列 
                select(Selection<? extends T> selection) : 查詢一列
                where(Predicate... restrictions) :  添加查詢條件
                orderBy(Order... o): 排序
            Root
                對查詢的持久化類中的屬性做了封裝.
                Path path =  root.get("屬性名");
                join() : 關聯(lián)查詢 root.join("teacher", JoinType.INNER);
                fetch() : 抓取連接.
            Path
                代表一個屬性
        使用
            查詢所有的學生
                CriteriaBuilder builder = em.getCriteriaBuilder();
                CriteriaQuery<Student> cq = builder.createQuery(Student.class);
                Root<Student> root = cq.from(Student.class);
                List<Student> lists = em.createQuery(cq).getResultList();
            查詢一列
                CriteriaBuilder builder = em.getCriteriaBuilder();
                CriteriaQuery<String> cq = builder.createQuery(String.class);
                Root<Student> root = cq.from(Student.class);
                Path<String> name = root.get("name");
                cq.select(name);
                List<String> lists = em.createQuery(cq).getResultList();
            查詢多列
                CriteriaBuilder builder = em.getCriteriaBuilder();
                CriteriaQuery<Object[]> cq = builder.createQuery(Object[].class);
                Root<Student> root = cq.from(Student.class);
                Path<String> name = root.get("name");
                Path<Integer> age = root.get("age");
                cq.multiselect(name, age);
                List<Object[]> lists = em.createQuery(cq).getResultList();
            添加查詢條件
                CriteriaBuilder builder = em.getCriteriaBuilder();
                CriteriaQuery<Student> cq = builder.createQuery(Student.class);
                Root<Student> root = cq.from(Student.class);
                Path<String> name = root.get("name");
                Path<Integer> age = root.get("age");
                cq.where(builder.like(name, "%小%"), builder.between(age, 19, 200));
                List<Student> lists = em.createQuery(cq).getResultList();
            排序
                CriteriaBuilder builder = em.getCriteriaBuilder();
                CriteriaQuery<Student> cq = builder.createQuery(Student.class);
                Root<Student> root = cq.from(Student.class);
                Path<String> age = root.get("age");
                cq.orderBy(builder.desc(age));
                List<Student> lists = em.createQuery(cq).getResultList();
            統(tǒng)計函數(shù)
                CriteriaBuilder builder = em.getCriteriaBuilder();
                CriteriaQuery<Integer> cq = builder.createQuery(Integer.class);
                Root<Student> root = cq.from(Student.class);
                Path<Integer> age = root.get("age");
                cq.select(builder.sum(age));
                Integer res = em.createQuery(cq).getSingleResult();
            關聯(lián)查詢
                CriteriaBuilder builder = em.getCriteriaBuilder();
                CriteriaQuery<Student> cq = builder.createQuery(Student.class);
                Root<Student> root = cq.from(Student.class);
                root.join("teacher", JoinType.INNER);
                Path<Integer> t_id = root.get("teacher").get("id");
                cq.where(builder.equal(t_id, 1));
                List<Student> lists = em.createQuery(cq).getResultList();
            抓取連接
                CriteriaBuilder builder = em.getCriteriaBuilder();
                CriteriaQuery<Student> cq = builder.createQuery(Student.class);
                Root<Student> root = cq.from(Student.class);
                root.fetch("teacher", JoinType.INNER);
                List<Student> lists = em.createQuery(cq).getResultList();

hibernate逆向工程

1.準備myeclipse
2.window-->show view-->DB browser
3.在db browser中 new 數(shù)據(jù)庫
    Driver timplate 選擇 mysql
    Driver name 直接寫一個別名
    Connection URL :jdbc:mysql:///test
    user name:root
    password:root
    Driver JARS:驅(qū)動包位置
    Driver className:com.mysql.jdbc.Driver
4.創(chuàng)建一個新的webhibernate項目
5.右鍵webhibernate項目-->myeclipse-->project facts[capabilities]-->install hibernate facet
6.設置hibernate版本 hibernate specification version :3.3
7.設置targer runtime :myeclipse generic runtime for javaee 6.0
8.需要配置文件hibernate.cfg.xml
9.java源碼配置java.package:com.shuai.test
10.className:HibernateSessionFactory
11.設置一個DB driver:第三步配置過了
12.添加包
13.選擇要逆向的表
    右鍵-->hibernate reverse Engineering
14.選擇java package 選擇路徑
15.create pojo
16.create data object
17.finish即可

OpenSessionInView

在過濾器/攔截器中開啟session,在jsp頁面處理完數(shù)據(jù)之后,再關閉session即可
Interceptor
    public class SessionInterceptor  extends AbstractInterceptor {
        @Override
        public String intercept(ActionInvocation invocation) throws Exception {
            Transaction tx = null;
            try {
                // 1. 創(chuàng)建session
                Session session = HibernateUtils.getSession();
                // 2. 開啟事務
                tx = session.beginTransaction();
                // 3. 放行
                String result = invocation.invoke();  //  // execute處理完,就表示 jsp已經(jīng)處理完畢
                return result;
            } catch (Exception e) {
                tx.rollback();
                e.printStackTrace();  // 打印錯誤信息!
                return "error";
            } finally {
                // 4. (執(zhí)行完action.execute方法), 提交事務
                tx.commit();
            }
        }
    }
HibernateUtils
    public class HibernateUtils {
        private static SessionFactory sf;
        static {
            sf = new Configuration().configure().buildSessionFactory();
        }
        public static Session getSession() {
            return sf.getCurrentSession();
        }
    }
Controller
    public class DeptAction extends ActionSupport{
        private int id;
        public void setId(int id) {
            this.id = id;
        }
        private Dept dept;
        public Dept getDept() {
            return dept;
        }
        public void setDept(Dept dept) {
            this.dept = dept;
        }
        // 創(chuàng)建service
        private DeptService deptService = new DeptService();
        @Override
        public String execute() throws Exception {
            // 主鍵查詢
            dept = deptService.findById(id);
            return SUCCESS; // execute處理完,就表示 jsp已經(jīng)處理完畢
        }
    }
jsp使用
    <s:iterator value="dept.employees">
        <tr>
            <td><s:property value="id"/></td>
            <td><s:property value="name"/></td>
            <td><s:property value="age"/></td>
        </tr>
    </s:iterator>

session的創(chuàng)建方式

第一種方式-openSession 
    Session session = sf.openSession();
    注意:
        1.每次獲取的Session不同
        2.可以不使用事務
第二種方式-線程方式創(chuàng)建Session
    Session session = sf.getCurrentSession();
    注意:
        1.一定要配置以線程的方式創(chuàng)建Session
            <property name="hibernate.current_session_context_class">thread</property>
        2.創(chuàng)建的Session,提交事務,自動關閉session
        3.使用getCurrentSession方法必須要有事務環(huán)境

聯(lián)合主鍵

Keys.java - 聯(lián)合主鍵,必須實現(xiàn)可序列化標記
    public class Keys implements Serializable{
        private String name;
        private String address;
    }
User.java
    public class User {
        private Keys key;
        private int age;
    }
User.hbm.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="cn.itcast.composite" auto-import="true">
        <class name="User" table="t_user_key">
            <composite-id name="key">
                <key-property name="name"></key-property>
                <key-property name="address"></key-property>
            </composite-id>
            <property name="age"></property>
        </class>
    </hibernate-mapping>
AppTest.java
    @Test
    public void save() {
        Session session = sf.openSession();
        session.beginTransaction();
        Keys key = new Keys();
        key.setName("Jack");
        key.setAddress("gz");
        User user = new User();
        user.setKey(key);
        user.setAge(20);
        session.save(user);
        session.getTransaction().commit();
        session.close();
    }
    @Test
    public void get() {
        Session session = sf.openSession();
        session.beginTransaction();
        Keys key = new Keys();
        key.setName("Jack");
        key.setAddress("gz");
        User user = (User) session.get(User.class, key);
        System.out.println(user.getKey().getName());
        System.out.println(user.getKey().getAddress());
        System.out.println(user.getAge());
        session.getTransaction().commit();
        session.close();
    }

基礎hql查詢

//查詢?nèi)?@Test
public void queryAll() {
    Session session = sf.openSession();
    session.beginTransaction();
    Query q = session.createQuery("from User");
    List<User> list = q.list();
    session.getTransaction().commit(); 
    session.close();
}
//刪除
@Test
public void delete() {
    Session session = sf.openSession();
    session.beginTransaction();
    Query q = session.createQuery("delete from User where id=1)");
    q.executeUpdate();
    session.getTransaction().commit(); 
    session.close();
}
//分頁
@Test
public void page() {
    Session session = sf.openSession();
    session.beginTransaction();
    Query q = session.createQuery("from User");
    // 設置分頁參數(shù)
    q.setFirstResult(0);  //相當于 limit 第一個參數(shù)  查詢的其實行
    q.setMaxResults(2);   //相當于 limit 第二個參數(shù) 查詢返回的行數(shù)
    List list = q.list();
    session.getTransaction().commit(); 
    session.close();
}

Hql查詢

API
    Query
        list();//查詢?nèi)?    
Query query = session.createQuery("from User");
List<user> list = query.list();//會懶加載 
    注意:會有一級緩存,緩存數(shù)據(jù).一個id的數(shù)據(jù)只查詢一次
連接查詢
    Query query = session.createQuery("from Address a inner join a.user");
    List<Object[]> list = query.list();//即時查詢,連接查詢可以解決懶加載問題.

fetch查詢
    把右表的數(shù)據(jù)填充到左表
    添加fetch查詢語句sql沒有任何變化,變化的是封裝數(shù)據(jù)的方式
    Query query = session.createQuery("from Address a inner join a.user"); 
    Query query = session.createQuery("from Address a inner join fetch a.user"); 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容