Hibernate知识宝库
hibernate3 | |||||
参考书 | 《javaweb程序设计与项目实践》古乐声 | ||||
版本说明 | 以hibernate3.3.2为例 | ||||
下载地址 | http://sourceforge.net/projects/hibernate/files/hibernate3/ (hibernate4的下载把3换成4) | ||||
项目配置步骤 | 以下以纯手工方式描述(可脱离MyEclipse、Eclipse等IDE),使用数据库管理系统是mySQL。 一.引入jar包 1、Hibernate的必备jar包;(application则用classpath引入,web程序则放入\WEB-INF\lib) (1)核心包:Hibernate3.jar; (2)lib\required下的6个jar包: antlr-2.7.6.jar commons-collections-3.1.jar dom4j-1.6.1.jar javassist-3.9.0.GA.jar jta-1.1.jar slf4j-api-1.5.8.jar (需slf4j的包来配合才能起作用) (3)slf4j-nop-1.5.8.jar(来自http://www.slf4j.org/,版本要和lib\required下的slf4j-api-1.5.8.jar数字匹配); 2、数据库驱动jar包;(application则用classpath引入,web程序则放入\WEB-INF\lib) 如mySQL驱动包mysql-connector-java-5.0.8-bin.jar
二.创建Hibernate配置文件(application则放入src目录,web程序则放入\WEB-INF\classes) (这里主要举XML文件的方式,其它方式见后文。) XML文件:hibernate.cfg.xml;(这是习惯文件名。DTD为:hibernate-configuration-3.0.dtd。) 主要是在根节点<hibernate-configuration>下的唯一一个子节点<session-factory>下配置数据库。
三.创建会话工厂类(该工厂类用于获得一个Session对象。每个线程对应唯一的Session对象。线程安全),使用者可以不关心会话工厂类内部细节,只管使用。
插件Myeclipse可以辅助生成会话工厂类文件HibernateSessionFactory。 如果用注释@配置实体-关系映射,则会话工厂类为AnnotationSessionFactory,内部代码细微区别。 如果脱离MyEclipse等插件,则需手工拷贝一份会话工厂类文件来用。
四、创建持久化类。(POJO类,成员变量都是private的,具有public的getterXXX/setterXXX方法)
五、创建“对象-关系”映射文件。 (1)对象-关系映射文件名:持久化类名.hbm.xml。 (与持久化类同目录。DTD文件为:hibernate-mapping-3.0.dtd。) 根节点<hibernate-mapping>。<class>节点指定了持久化类。 (2)在hibernate.cfg.xml添加<mapping resource=”映射文件路径” />(注:必须在property后)
(如果是用注释Annotation的方案,则不需要映射文件,且在hibernate.cfg.xml中添加的形式为<mapping class=”持久化类路径” />)
至此时,已形成了4者关联:数据库—hibernate.cfg.xml—映射文件—持久化类。
六、操作数据库 调用会话工厂类来先得到Session,再用该Session(org.hibernate.Session)来操作数据。写数据时需要用到Transaction (org.hibernate.Transaction)。 | ||||
备注 | 1.hibernate.cfg.xml文件中<property name=”show_sql”>false</property>设置了在进行持久化操作时,是否会将相应的SQL语句输出到控制台。 2. hibernate的数据库输出日志为log4j,可以设置是否在控制台输出,与log4j.property文件有关。最好将logforj配置上。这样方便调试。 3. 有的工具能:自动根据映射文件(持久化类)生成表的功能, 有的工具能:根据表自动生成“持久化类”和“映射文件”。如MyEclipse的DBBrowser视图 | ||||
配置文件相关说明 | 配置hibernate的方案 法一:使用文件hibernate.cfg.xml:一个文件只能配置一个数据库连接信息 若使用其它文件名,则在HibernateSessionFactory类中相应设置。 法二:使用资源文件“*.property”。已过时。 法三:动态配置,用一个类的configuration对象来配置,调用多个setProperty(“键”,”值”)方法。 | ||||
配置“对象-关系”映射(文件) 法一:使用文件“持久化类名.hbm.xml” 法二:使用JDK5.0后推出的注释技术Annotations 注释实体类:@Entity、@Table。 注释实体类标识:@Id、@GeneratedValue、@GenericdValue、@GenericGenerator。 注释实体类非标识:@Column。 | |||||
关联关系下的映射配置 | 多 对 一、
一 对 多、 | 示例 | “学生”实体与“班级”实体的关系。“学生”为“多”方,“班级”为“一”方。一个“班级”实体对应了多个“学生”实体。一个“学生”实体最多能对应一个“班级”实体。 具体测试结果见http://ryxxlong.iteye.com/category/98071中相关文章 | ||
数据表定义 | 建表方式:将“一”方的主键做为“多”方表定义的外键。 create table student ( studentID int(11) not null auto_increment , studentName varchar(10) default NULL, classID int(11) default NULL, PRIMARY KEY(studentID), FOREIGN KEY(classID) references classes(classID) );
create table classes( classID int(11) not null auto_increment , className varchar(30) default NULL, PRIMARY KEY(classID) ); | ||||
以“多”方为主控方 | 实体类定义 | public class Student { //学生类 private int studentID; //学生编号 private String studentName; //学生姓名 private Classes myClass; //学生班级 } | |||
映射文件定义 | <hibernate-mapping> <class name="com.sanqing.po.Student" table="student"> <id name="studentID"> <generator class="identity"></generator> </id> <property name="studentName"></property>
<many-to-one name="myClass" column="classID" class="com.sanqing.po.Classes" cascade="all" outer-join="true"/> </class> </hibernate-mapping> | ||||
以“一”方为主控方 | 实体类定义 | public class Classes { //班级类 private int classID; //班级编号 private String className; //班级名称 private Set<Student> students;//班级中的所有学生 } | |||
映射文件定义 | <hibernate-mapping> <class name="com.sanqing.po.Classes" table="classes"> <id name="classID"> <generator class="identity"></generator> </id> <property name="className"></property> <set name="students" cascade="all" lazy="true"> <key column="classID"></key> <!-- 配置外键 --> <one-to-many class="com.sanqing.po.Student"/><!-- 配置关联类 --> </set> </class> </hibernate-mapping> | ||||
一 对 一 | 示例 | “人”实体与“身份证”实体的关系。一个“人”只有一个“身份证”,一个“身份证”只能对应一个“人”。 具体测试结果见http://ryxxlong.iteye.com/category/98071中相关文章 | |||
数据表定义 | 建表方式:将其中一方表的主键做为另一方表定义的外键,并将该外键也设置为具有“唯一”的特性。 两方均可做主控方。
create table person ( id int(11) not null auto_increment , personName varchar(20) default NULL, cardID int(11) default NULL, PRIMARY KEY(id), unique cardID(cardID), FOREIGN KEY(cardID) references card(id) );
create table card( id int(11) not null auto_increment , cardNO varchar(18) default NULL, PRIMARY KEY(id) ); | ||||
实体类定义 | public class Person { //人 private int id; //编号(自动编号) private String personName; //姓名 private Card card; //身份证号码 }
public class Card { //身份证 private int id; //编号 private String cardNO;//身份证号码 private String place;//身份证发放地 private Person person;//所属人 } | ||||
映射文件定义 | <hibernate-mapping> <class name="com.sanqing.po.Person" table="person"> <id name="id"> <generator class="identity"></generator> </id> <property name="personName"></property> <!--配置一对一映射关系,一个人对应一个身份证信息--> <one-to-one name="card" class="com.sanqing.po.Card" cascade="all" unique="true"/> </class> </hibernate-mapping>
| ||||
<hibernate-mapping> <class name="com.sanqing.po.Card" table="card"> <id name="id"> <generator class="identity"></generator> </id> <property name="place"></property> <!-- 配置place属性 --> <property name="cardNO"></property> <!-- 配置cardNO属性 --> <one-to-one name="person" property-ref="card"></one-to-one> </class> </hibernate-mapping> 在被控方可以不用配置<one-to-one>标签。 | |||||
多对多 | 多对多实际上最终会转换成一对多、多对一关系。比如选课这件事情,与“学生”、“课程”相关。学生与课程本是多对多的关系,但处理方式是定义“选课”实体:(编号、学生、课程),“选课”与“学生”是“多对一”的关系,“选课”与“课程”也是“多对一”的关系。 | ||||
操作数据库的常用代码常用格式。
主要区分用于“写”和“读”的代码的区别 | 写(增、删、改)数据的常用格式举例,写数据必须考虑事务性: import org.hibernate.Session; import org.hibernate.Transaction; import com.sanqing.hibernate.HibernateSessionFactory; …... Session s=HibernateSessionFactory.getSession();//获得Session对象 Transaction t = null; //声明一个事务对象 try{ t=s.beginTransaction(); //开启事务 s.save(持久化对象变量名); //写入数据 t.commit(); //提交事务 } catch(Exception e){ e.printStackTrace(); t.rollback(); //事务回滚 }
HibernateSessionFactory.closeSession();//关闭Session对象 …... | ||||
读(查询)数据的常用格式举例(本例的持久化类是Student),读数据可以不考虑事务性: import java.util.Iterator; import java.util.List; import org.hibernate.Query; import org.hibernate.Session;
import com.sanqing.hibernate.HibernateSessionFactory; import com.sanqing.po.Student;
public class QueryTest { public static void main(String[] args) { Session session = HibernateSessionFactory.getSession();// 获得Session对象 Query query = session.createQuery (“from Student as stu where stu.subject = ‘大学英语’ and stu.result >= 60”);// 查询student表 List list = query.list();// 查询结果保存到list中 Iterator iter = list.iterator();// 获得list的内部迭代器 Student stu = null; System.out.println(“学号\t\t姓名\t科目\t成绩”); while (iter.hasNext()) { // 遍历list stu = (Student) iter.next(); System.out.println(stu.getId() + "\t" + stu.getName() + "\t" + stu.getSubject() + "\t" + stu.getResult()); } HibernateSessionFactory.closeSession();// 关闭Session对象 } } | |||||
Session的一些方法(更多的方法见相关文档) | 1.持久化(写入):save()、saveOrUpdate(): 将内存对象写入到数据库记录去。推荐saveOrUpdate()。 2.刷新:refresh(): 比对数据库记录和内存对象,以数据库记录为准来刷新内存对象。 3.更新:update():比对数据库记录和内存对象,以内存对象为准去修正数据库记录。 可能后续需要调用flash()以使更新生效,但不一定必须调用flash()。这与更新模式FlushMode有关。可以setFlushMode(FlushMode常量),FlushMode的常量有MANUAL、COMMIT、AUTO、ALWAYS。 比如一旦某内存对象是某session从数据库中装载得到的,如果此时FlushMode等于AUTO,此后,如果修改了内存对象,当提交事务时Transaction.commit(),session会自动调用flash()。要注意区分FlushMode等于不同值所起到的效果。 4.装载:load()、get(): 从数据库记录读出,并创建内存对象。Serializable标识Id作为选择记录的依据。推荐get()。 5.比较:isDirty(): 比对数据库记录和内存对象是否一致,返回true或false。涉与session有关的所有当前内存对象。 6.删除:delete(): 将内存对象对应的数据库记录删除。 | ||||
标准查询API | 需利用org.hibernate.Criteria接口。 步骤是: 1、Criteria c=session.creatCriteria(类类型)可创建Criteria接口对象。 2、Criteria的list()方法可以得到查询结果。 3、后续处理。 (注:session.creatCriteria(类类型)的参数是类,说明hibernate会自行找到对应的表) | ||||
Criteria支持的设置有: 1、设置最大记录数setMaxResults(); 2、设置条件add(Criterion);条件甚至支持通配符或MatchMode模糊); (Criterion接口代表一些条件约束。具体可用如Restrictions类的静态方法得到实现了Criterion的对象) 3、设置Order类来定制排序规则。 | |||||
HQL查询 | 需利用org.hibernate.Query接口。 步骤是: 1、Query query = session.createQuery(字符串) 可创建Query接口对象。 2、Query的list()方法可以得到查询结果。 3、后续处理。 (注:字符串如果是“from 名字”的形式,则名字是实体类名,list()返回值将是list<类名>;否则是sql语句,list()返回值将是list<Object[]>) |