一:使用配置文件开发
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只能在“一”的一方来配置!