1,使用Hibernate操作数据库需要七个步骤
(1)读取并解析配置文件(hibernate3.6以下版本)
Configuration conf = new Configuration().configure();
(2)读取并解析映射信息,创建SessionFactory
SessionFactory sf = conf.buildSessionFactory();
(3)打开Session
Session session = sf.openSession();
(4)开始一个事务(增删改操作必须,查询操作可选)
Transaction tx = session.beginTransaction();
(5)数据库操作
session.save(user);//或其它操作
(6)提交事务(回滚事务)
tx.commit();(tx.rollback();)
(7)关闭session
session.close();
2,Configuration:负责管理Hibernate的配置信息,这些配置信息都是从配置文件hibernate.cfg.xml或者Hibernate.properties读取的,当然也可以自定义文件名称,只要在实例化Configuration的时候指定具体的路径就可以了。
SessionFactiory:Configuration的实例会根据当前的配置信息,构造SessionFactory实例。SessionFactory是线程安全的,一般情况下一个应用中一个数据库共享一个SessionFactory实例。Hibernate的SessionFactory接口提供Session类的实例,Session类用于完成对数据库的操作。由于SessionFactory实例是线程安全的(而Session实例不是线程安全的),所以每个操作都可以共用同一个SessionFactory来获取Session。
Session:一般的持久化方法(CRUD)都是通过Session来调用的,Session是非线程安全的。Session的创建与关闭 :Session是一个轻量级对象,通常将每个Session实例和一个数据库事务绑定,也就是每执行一个数据库事务,都应该先创建一个新的Session实例,在使用Session后,还需要关闭Session。
Hibernate中配置主要分为两种:一种包含了Hibernate与数据库的基本连接信息,在Hibernate工作的初始阶段,这些信息被先后加载到Configuration和SessionFactory实例;另一种包含了Hibernate的基本映射信息,即系统中每一个类与其对应的数据库表之间的关联信息,在Hibernate工作的初始阶段,这些信息通过hibernate.cfg.xml的mapping节点被加载到Configuration和SessionFactory实例。下面我们看一下带有详细注释的hibernate.cfg.xml。
<!--标准的XML文件的起始行,version='1.0'表明XML的版本,encoding='gb2312'表
明XML文件的编码方式-->
<?xml version='1.0'encoding='gb2312'?>
<!--表明解析本XML文件的DTD文档位置,DTD是DocumentType Definition 的缩写,
即文档类型的定义,XML解析器使用DTD文档来检查XML文件的合法性。
hibernate.sourceforge.net/hibernate-configuration-3.0dtd可以在
Hibernate3.1.3软件包中的src\org\hibernate目录中找到此文件-->
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!--声明Hibernate配置文件的开始-->
<hibernate-configuration>
<!--表明以下的配置是针对session-factory配置的,SessionFactory是
Hibernate中的一个类,这个类主要负责保存HIbernate的配置信息,以及对Session的
操作-->
<session-factory>
<!--配置数据库的驱动程序,Hibernate在连接数据库时,需要用到数据库的驱
动程序-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!--设置数据库的连接url:jdbc:mysql://localhost/hibernate,其中localhost表示mysql服务器名称,此处为本机,hibernate是数据库名-->
<property name="hibernate.connection.url"> jdbc:mysql://localhost/hibernate</property>
<!--连接数据库是用户名-->
<property name="hibernate.connection.username">root</property>
<!--连接数据库是密码-->
<property name="hibernate.connection.password">123456</property>
<!--数据库连接池的大小-->
<propertyname="hibernate.connection.pool.size">20</property>
<!--是否在后台显示Hibernate用到的SQL语句,开发时设置为true,便于差错,程序运行时可以在Eclipse的控制台显示Hibernate的执行Sql语句。项目部署后可
以设置为false,提高运行效率-->
<propertyname="hibernate.show_sql">true</property>
<!--jdbc.fetch_size是指Hibernate每次从数据库中取出并放到JDBC的Statement中的记录条数。FetchSize设的越大,读数据库的次数越少,速度越快,Fetch Size越小,读数据库的次数越多,速度越慢-->
<propertyname="jdbc.fetch_size">50</property>
<!--jdbc.batch_size是指Hibernate批量插入,删除和更新时每次操作的记录数。BatchSize越大,批量操作的向数据库发送Sql的次数越少,速度就越快,同样
耗用内存就越大-->
<propertyname="jdbc.batch_size">23</property>
<!--jdbc.use_scrollable_resultset是否允许Hibernate用JDBC的可滚动的结果集。对分页的结果集。对分页时的设置非常有帮助-->
<propertyname="jdbc.use_scrollable_resultset">false</property>
<!--connection.useUnicode连接数据库时是否使用Unicode编码-->
<propertyname="Connection.useUnicode">true</property>
<!--connection.characterEncoding连接数据库时数据的传输字符集编码方式,最好设置为gbk,用gb2312有的字符不全-->
<propertyname="connection.characterEncoding">gbk</property>
<!--hibernate.dialect 只是Hibernate使用的数据库方言,就是要用Hibernate连接那种类型的数据库服务器。-->
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect</property>
<!-是否自动创建数据库表 他主要有一下几个值:
validate:当sessionFactory创建时,自动验证或者schema定义导入数据库。
create:每次启动都drop掉原来的schema,创建新的。
create-drop:当sessionFactory明确关闭时,drop掉schema。-->
<mapping class="com.zj.hiberate.Card"/> <!-对应数据库表中的实体类-->
<mapping class="com.zj.hiberate.User"/>
</session-factory>
</hibernate-configuration>
关系映射
1,一对一单向外键关联映射(图中表示Husband依赖wife,也就是表示生成的husband表中会有wife id属性字段,wife表中没有husband id)
对应的Husband类中应加入wife成员变量,同时在wife变量的get方法上应加入如下注解
@OneToOne
@JoinColumn(name="wife") //不加这句数据库中会生成一张关联表;
public Wife getWife() {
return wife;
}
2,一对一双向外键关联映射(Husband和Wife表中都有对方的id字段)
对应的Husband和wife类中都有对方的成员变量,此时需要在Husband类中
@OneToOne(mappedBy="wife")
public Husband getHusband() {
return husband;
}
在Wife类中
@OneToOne(mappedBy="wife")
public Husband getHusband() {
return husband;
}
3,多对一关系映射和单向一对多关系映射
多个用户属于一个组,我们用多的一方来维护,所以我们可以根据用户可以知道他在哪个组,而不需要知道一个组里有哪些学生,这就是所谓的单向的。多对一映射原理:在多的一端加入一个外键指向一的一端,它维护的关系多指向一,一对多映射原理,在多的一端加入一个外键指向一的一端,她维护的关系是一指向多,也就是说一对多与多对一的映射原理是一样的,只是站的角度不一样。
以user和Group对象为例
多对一单向映射User和Group,需要在多的一方加入外键,也就是在User类中加入Group成员变量,并且在get方法上加上@ManyToOne注解
@ManyToOne
@JoinColumn(name="groupId")//不加入这行,会在数据库生成关联表
public Group getGroup() {
return group;
}
一对多单向映射Group和User需在一的一方加入多的外键,也就是在Group中加入set成员变量.其对应注解为
@OneToMany
@JoinColumn(name="group_id")//不加入这行,会在数据库生成关联表
public Set<User> getUsers() {
return Users;
}
@JoinColumn就是加入外键的作用,无论是一对多还是多对一,对于数据库的表都是在多的一端表中加入外键。
4,一对多双向映射和多对一双向映射(本质一样,只是站的角度不同)
以Group和User,在group和user表中都有对方的主键,对应的实体类中有对方的实体成员变量,具体如下所示:Group类中user的set对象,user中有Group变量,user类中注解
@ManyToOne(cascade=CascadeType.ALL)
public Group getT_group() {
return t_group;
}
Group类中注解
@OneToMany(mappedBy="t_group",cascade=CascadeType.ALL)
public Set<User> getUsers() {
return Users;
}
无论是多对一还是一对多,最终生成的数据库的表中,都会在多的一端增加了一个外键来关联一的一端。OneToMany必须加入mappedby属性。
5,多对多双向映射
以User和Card为例,user有多张card,card也有多个user
user中注解
@ManyToMany
@JoinTable(name="u_c",joinColumns=@JoinColumn(name="users"),inverseJoinColumns=@JoinColumn(name="cards"))
public Set<Card> getCards() {
return cards;
}
card中注解
@ManyToMany(mappedBy="cards")
public Set<User> getUsers() {
return users;
}
ps:多对多一定会存在一张关联表,其中@JoinTable用于修改关联表的字段属性名称。