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