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只能在“一”的一方来配置!

 

posted @ 2017-11-12 22:34  阿苍老师  阅读(106)  评论(0编辑  收藏  举报