• Hibernate的应用及注解开发


    一:使用配置文件开发

    1:创建数据库表

    2:然后就是根据这个数据表创建一个对应的类

    复制代码
    public class HibernateDemo1 {
        
        private long cust_id;
        private String cust_name;
        private String cust_source;
        private String cust_industry;
        private String cust_level;
        private String cust_phone;
        private String cust_mobile;
        public long getCust_id() {
            return cust_id;
        }
        public void setCust_id(long cust_id) {
            this.cust_id = cust_id;
        }
        public String getCust_name() {
            return cust_name;
        }
        public void setCust_name(String cust_name) {
            this.cust_name = cust_name;
        }
        public String getCust_source() {
            return cust_source;
        }
        public void setCust_source(String cust_source) {
            this.cust_source = cust_source;
        }
        public String getCust_industry() {
            return cust_industry;
        }
        public void setCust_industry(String cust_industry) {
            this.cust_industry = cust_industry;
        }
        public String getCust_level() {
            return cust_level;
        }
        public void setCust_level(String cust_level) {
            this.cust_level = cust_level;
        }
        public String getCust_phone() {
            return cust_phone;
        }
        public void setCust_phone(String cust_phone) {
            this.cust_phone = cust_phone;
        }
        public String getCust_mobile() {
            return cust_mobile;
        }
        public void setCust_mobile(String cust_mobile) {
            this.cust_mobile = cust_mobile;
        }
        
    }
    复制代码

     3:下面就是配置类和数据表之间的关联。命名的规则是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的导包中找到-->
       
    <!--下面就是开始创建对应的映射关系-->
     <hibernate-mapping>
     <!-- 建立类与表的映射 -->
        <class name="com.hibernate.learn.HibernateDemo1" table="cst_customer">
               <!--  建立类中的属性与表中的主键对应-->
               <id name="cust_id" column="cust_id">
                   <generator class="native"></generator>
               </id>
               <!-- 建立类中的普通的属性和表中字段的对应。除了主键用id其他都用property -->
               <property name="cust_name" column="cust_name"></property>
               <property name="cust_source" column="cust_source"></property>
               <property name="cust_industry" column="cust_industry"></property>
               <property name="cust_level" column="cust_level"></property>
               <property name="cust_phone" column="cust_phone"></property>
               <property name="cust_mobile" column="cust_mobile"></property>
        </class>
     </hibernate-mapping>
    复制代码

    至此映射关系配置完毕

    4:下面需要做的是数据库连接的配置文件,这个文件的命名格式是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的相关配置-->    
    <hibernate-configuration>
        <session-factory>
        <!-- 连接数据库的基本配置。这块属于数据库的固定配置模式,这里的数据库是mysql数据库-->
             <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
             <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
             <property name="hibernate.connection.username">root</property>
             <property name="hibernate.connection.password">root</property>
             <!-- 配置Hibernate的方言。意思是指你采用的是什么数据库,因为mysql,orcle等很多数据库的要求是不一样的。所以要在此处进行配置 -->
             <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
             
             <!-- 打印sql语句到控制台,不是必须要有的配置-->
             <property name="hibernate.show_sql">true</property>
             
              <!-- 自动建表的配置 -->
             <property name="hibernate.hbm2ddl.auto">update</property>
             
             
             <!-- 配置C3P0连接池 .如果需要使用c3p0可以通过这种方式来完成导入-->
            <property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
            <!--在连接池中可用的数据库连接的最少数目 -->
            <property name="c3p0.min_size">5</property>
            <!--在连接池中所有数据库连接的最大数目  -->
            <property name="c3p0.max_size">20</property>
            <!--设定数据库连接的过期时间,以秒为单位,
            如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
            <property name="c3p0.timeout">120</property>
             <!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
            <property name="c3p0.idle_test_period">3000</property>
             
             
             <!-- 格式化sql,是控制台输出的数据库语句更加美观,不是必须要有的配置 -->
             <property name="hibernate.format_sql">true</property>
             
             <!--最终映射到刚刚的类与数据表映射的配置文件xxx.hbm.xml-->
             <mapping resource="com/hibernate/learn/Hibernate.hbm.xml"></mapping>
        </session-factory>
    </hibernate-configuration>
    复制代码

    至此Hibernate的相关配置完成

    5:最后开始对数据库经行操作

    复制代码
    public static void main(String[] args) throws SecurityException, HeuristicMixedException, HeuristicRollbackException, RollbackException, SystemException {
            //保存客户的案例
            //1.加载Hibernate核心配置文件
            Configuration configuration=new Configuration().configure();
            
            //2.创建一个SessionFactory对象:类似于JDBC中连接池
            SessionFactory sessionFactory=configuration.buildSessionFactory();
            
            //3.通过SessionFactory获取到Session对象,类似于JDBC中的Connection
            Session session=sessionFactory.openSession();
            
            //4.手动开启事务:
            Transaction transaction=(Transaction) session.beginTransaction();
            
            //5.编写代码
            HibernateDemo1 hibernateDemo1=new HibernateDemo1();
            
            hibernateDemo1.setCust_name("zyz");
            session.save(hibernateDemo1);
            
            //6.事务提交
            transaction.commit();
            
            //7.释放资源
            session.close();
        }
    
    OK至此相关的简单的案例完成
    复制代码

     二:Hibernate注解开发

    1:创建数据库表

    2:根据数据库表创建实体类,并根据其添加注解

     1 @Entity // 定义了一个实体
     2 @Table(name="cst_customer",catalog="hibernateTest")
     3 public class HibernateDemo1 {
     4     @Id // 这表示一个主键
     5     // @GeneratedValue 相当于native主键生成策略
     6     @GeneratedValue(strategy=GenerationType.IDENTITY) // 相当于identity主键生成策略
     7     private long cust_id;
     8     @Column(name="c_name", length=30, nullable=true)
     9     private String cust_name;
    10 ……
    11 }

    常用注解有

    1:@Entity说明这个class是实体类,并且使用默认的orm规则,即class名即数据库表中表名,class字段名即表中的字段名
          如果想改变这种默认的orm规则,就要使用@Table(name="BigUser")来改变class名与数据库中表名的映射规则,@Column来改变class中字段名与db中表的字段名的映射规则

    2:   @Id:声明一个主键

    3:@GeneratedValue:用它来声明一个主键生成策略,默认情况是native主键生成策咯。可以选择的主键生成策略有:AUTO,identity,sequence

    4:@Column:定义列

    注意:就算在实体类内没有注解的字段也会在数据库表里生成响应的列

    5:@Temporal:声明日期类型

    6:@Transient   :忽略这些字段属性和属性,不用持久化到数据库

    7:Hibernate关联映射:

    一对一:@OneToOne

    一对多:@OneToMany

    多对一:@ManyToOne

    多对多:@ManyToMany

    案例:

     1 package com.webShop.domain;
     2 import java.io.Serializable;
     3 import java.util.Set;
     4 import javax.persistence.;
     5 //定义实体类
     6 @Entity
     7 public class User implements Serializable {
     8     /*定义ID*/
     9     @Id
    10     @GeneratedValue
    11     private int id;
    12     /*定义用户名*/
    13     @Column(length=20)
    14     private String username;
    15     /*定义密码*/
    16     @Column(length=20)
    17     private String password;
    18     /*定义身份证号*/
    19     @Column(length=20)
    20     private String cardId;
    21     /*定义变量进行级联操作,并不进行延迟加载,使用list是不能设定多个FetchType.EAGER的,使用set可以*/
    22     @OneToMany(cascade={CascadeType.ALL},fetch=FetchType.EAGER,mappedBy="user")
    23     private Set<Address> address;
    24     @OneToMany(cascade={CascadeType.ALL},fetch=FetchType.EAGER,mappedBy="user")
    25     private Set<Depatement> department;
    26     @OneToMany(cascade={CascadeType.ALL},fetch=FetchType.EAGER,mappedBy="user")
    27     private Set<Phone> phone;
    28     @OneToMany(fetch=FetchType.EAGER,mappedBy="user")
    29     @OrderBy("id ASC")
    30     private Set<ShoppingLog> shoppingLog;
    31 //    不持久化该变量
    32     @Transient
    33     private String password1;
    34 //    构造函数
    35     
    36     public User(String username,String password,String cardId){
    37         this.username = username;
    38         this.password = password;
    39         this.cardId = cardId;
    40         
    41     }
    42 //默认构造方法
    43     public User(){
    44    }
    45 //省略getter和setter方法    
    46 }

    3:在hibernate.cfg.xml文件将类中注解配置引用生效

    <mapping class="cn.xqc.domain.HibernateDemo1 "/>

    4:最后开始对数据库经行操作

    同上

    三:基本原理和其他问题

    1:Hibernate工作原理

    • 1.读取并解析配置文件 
    • 2.读取并解析映射信息,创建SessionFactory 
    • 3.打开Sesssion 
    • 4.创建事务Transation 
    • 5.持久化操作 
    • 6.提交事务 
    • 7.关闭Session 
    • 8.关闭SesstionFactory

    2. get(立即查询)和load(懒加载)区别;

    1)get如果没有找到会返回null, load如果没有找到会抛出异常。

    2)get会先查一级缓存, 再查二级缓存,然后查数据库;load会先查一级缓存,如果没有找到,就创建代理对象,等需要的时候去查询二级缓存和数据库。

    3、hibernate的数据三种状态 
    瞬时的(刚new出来的数据–内存有,数据库没有) 
    持久的 (从数据查询的,或者刚保存到数据库,session没关闭的, 数据库有,内存也有) 
    游离的 、脱管的(数据库有,内存没有)

    new user ——>  sesssion.save(user)——>transaction.commit();——>session.close();

    4. 简述hibernate的缓存机制 

    hibernate分为2级缓存 
    一级缓存又叫session缓存,又叫事务级缓存,生命周期从事务开始到事务结束,一级缓存是hibernate自带的,暴力使用,当我们一创建session就已有这个缓存了。数据库就会自动往缓存存放, 
    二级缓存是hibernate提供的一组开放的接口方式实现的,都是通过整合第三方的缓存框架来实现的,二级缓存又叫sessionFactory的缓存,可以跨session访问。常用的EHcache、OScache,这个需要一些配置。

    当我们每次 查询数据的时候,首先是到一级缓存查看是否存在该对象,如果有直接返回,如果没有就去二级缓存进行查看,如果有直接返回,如果没有在发送SQL到数据库查询数据, 
    当SQL发送查询回该数据的时候,hibernate会把该对象以主键为标记的形式存储到二级缓存和一级缓存,如果返回的是集合,会把集合打散然后以主键的形式存储到缓存。一级缓存和二级缓存只针对以ID查询的方式生效,get、load方法。

     5.Hibernate是如何延迟加载?

    通过设置属性lazy进行设置是否需要懒加载

    当Hibernate在查询数据的时候,数据并没有存在与内存中,当程序真正对数据的操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而

    提高了服务器的性能。

    6.Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)

    类与类之间的关系主要体现在表与表之间的关系进行操作,它们都市对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、

    one-to-many、many-to-many、

    7,Hibernate中的SessionFactory有什么作用? SessionFactory是线程安全的吗?


    这也是Hibernate框架的常见面试问题。顾名思义,SessionFactory就是一个用于创建Hibernate的Session对象的工厂。SessionFactory通常是在应用启动时创建好的,应用程序中的代码用它来获得Session对象。作为一个单个的数据存储,它也是 线程安全的,所以多个线程可同时使用同一个SessionFactory。

     13: session.commit 和flush区别, commit会先调用flash执行session清理,然后提交事物; flash执行session,但不一定提交事物(因为事物可能被委托给外围的aop代理来做);

    14:hibernate里面的sorted collection 和ordered collection有什么区别

    sorted collection

      • 是在内存中通过Java比较器进行排序的

    ordered collection

      • 是在数据库中通过order by进行排序的

    对于比较大的数据集,为了避免在内存中对它们进行排序而出现 Java中的OutOfMemoryError,最好使用ordered collection。

    15:Hibernate的查询方式有几种

    • 对象导航查询(objectcomposition)

    • HQL查询

      • 1、 属性查询

      • 2、 参数查询、命名参数查询

      • 3、 关联查询

      • 4、 分页查询

      • 5、 统计函数

    • Criteria 查询

    • SQLQuery本地SQL查询

    16:谈谈Hibernate中inverse的作用

    inverse属性默认是false,就是说关系的两端都来维护关系。

      • 比如Student和Teacher是多对多关系,用一个中间表TeacherStudent维护。Gp)

      • 如果Student这边inverse=”true”, 那么关系由另一端Teacher维护,就是说当插入Student时,不会操作TeacherStudent表(中间表)。只有Teacher插入或删除时才会触发对中间表的操作。所以两边都inverse=”true”是不对的,会导致任何操作都不触发对中间表的影响;当两边都inverse=”false”或默认时,会导致在中间表中插入两次关系。

    如果表之间的关联关系是“一对多”的话,那么inverse只能在“一”的一方来配置!

  • 相关阅读:
    Python学习日记(一)——初识Python
    读《乌合之众》
    用WPF做了几个小游戏
    《HeadFirst设计模式》读后感——对学习设计模式的一些想法
    设计模式C#实现(九)——工厂方法模式和简单工厂
    设计模式C#实现(八)——原型模式
    设计模式C#实现(七)——生成器模式
    设计模式C#实现(六)——单例模式
    《小强升职记》读后感和思维导图
    《魔鬼搭讪学》《魔鬼约会学》读后感
  • 原文地址:https://www.cnblogs.com/nullering/p/7790095.html
Copyright © 2020-2023  润新知