1.jar文件导入项目中
2.添加Hibernate.cfg.xml文件
3.创建数据库表
4.创建该表对应的持久化类PO
5.添加映射文件xxx.hbm.xml
6.添加SessionFactory工厂类
<!-- 一对多,并且子表列比较多,在程序中有对应的持久化类时 -->
<set name="students">
<!-- key指的是子表的外键列 -->
<key column="GID"/>
<!-- 指集合中的元素是哪个类型的对象 -->
<one-to-many class="com.pb.Student"/>
</set>
<!-- 多对一 -->
<many-to-one name="grade" class="com.pb.Grade">
<!-- 指定外键列 -->
<column name="GID"/>
</many-to-one>
<!-- 当使用外键实现一对一时: -->
<!-- 一对一,主动方 -->
<one-to-one name="paper" class="com.pb.Paper" cascade="all" lazy="false"/>
<!-- 多对一 ,被动方-->
<many-to-one name="student" class="com.pb.Student" unique="true" lazy="false">
<column name="SID"/>
</many-to-one>
<!-- 多对多,通过中间表,不增加持久化类 -->
<set name="courses" table="sc"><!-- table:中间表 -->
<key column="sid"/><!-- 当前表和中间表之间的外键,为中间表的列 -->
<!-- class:当前set中元素的类型。
column:中间表和课程表之间的外键,为中间表的列 -->
<many-to-many class="com.pb.Course" column="cid"/>
</set>
<!-- 一对多,并且子表只有外键列和值列 -->
<!-- name指集合属性名,table指集合数据是从哪个表来的 -->
<set name="images" table="IMAGES">
<!-- key指的是子表的外键列 -->
<key column="userId"/>
<!-- 指集合中的元素是从子表的哪个列取出来的 -->
<element column="FILENAME" type="string"/>
</set>
<!-- 一对多,并且子表有三个列:外键、索引列、值列 -->
<!-- name指的是集合属性名, table指集合数据是从哪个表来的 -->
<list name="images" table="IMAGES">
<!-- key指的是子表的外键列 -->
<key column="userId"/>
<!-- list-index指的是子表的索引列 -->
<list-index column="POSITION"/>
<!-- 指集合中的元素是从子表的哪个列取出来的:值列 -->
<element column="FILENAME" type="string"/>
</list>
<!-- 一对多,并且子表有三个列:外键、键列、值列 -->
<!-- name指的是集合属性名, table指集合数据是从哪个表来的 -->
<map name="images" table="IMAGES">
<!-- key指的是子表的外键列 -->
<key column="userId"/>
<!-- 指键列是字表的哪个列 -->
<map-key column="IMAGE_NAME" type="string"/>
<!-- 指集合中的元素是从子表的哪个列取出来的:值列 -->
<element column="FILENAME" type="string"/>
</map>
HQL: 查询属性和类名
1.创建Query对象
2.调用相应方法获得结果
2.1.执行查询:
list()查询一次,
iterator()查询1+n次,
uniqueResult()查询一条记录
2.2.更新、删除
executeUpdate()
1.查询所有列,不带条件
from 类名
2.查询所有列,带条件
2.1.拼接字符串
String hql = "from 类名 where 属性1=‘"+变量+"‘
2.2.使用问号占位符
String hql = "from 类名 where 属性1=?"
2.1.使用命名参数
String hql = "from 类名 where 属性1=:参数名1"
3.查询某些列,不带条件
select 属性1,...属性n from 类名
查出的结果是List<Object[]>
4.查询一个列,不带条件
select 属性1 from 类名
查出的结果是List<Object>
5.查询某些列,不带条件,以对象封装
select new 类名(属性1,...属性n) from 类名
查出的结果是List<类名>
6.连接查询
String hql="from 类名 join 当前类的连接属性"
Student grade
7.检索策略
7.1.类级别
只对load方法起作用。
Grade.hbm.xml里面的<class>标签添加属性lazy="true/false",默认是true
表现:当执行load方法时,并不执行sql语句,而是创建一个只有oid值的代理对象;当访问该对象的非oid属性时,执行sql
7.2.关联级别
对所有查询方法都有效。
Grade.hbm.xml里面的关联集合属性<set>中添加lazy="true/false",默认是true
表现:当执行查询方法时,只执行对主表查询的sql语句;当访问该对象的关联集合属性时,执行对子表查询的sql语句
7.3.批量检索
Grade.hbm.xml里面的关联集合属性<set>中添加batch-size="2~10".在查询关联集合对象时批量查询,提交查询性能
7.4.Fetch:通过什么查询语句查询关联集合对象
select,subselect(都支持立即检索或延迟检索),
join(立即检索):1.只支持立即检索,忽略lazy属性;2.不支持hql查询,只支持get和load
Criteria标准查询
Criteria ct = session.createCriteria(Grade.class);
ct.add(Restrictions.eq("gid",1001));
ct.add(Restrictions.or(
Restrictions.eq("age",20),
Restrictions.like("username","%马%")
));
ct.add(Restrictions.between("gid",1001,1003));
ct.add(Restrictions.in("gid",new Integer[]{1001,1002,1003}));
ct.addOrder(Order.desc("gid"));//降序排列,Order.asc()升序
//示例查询:条件较多,且都是等值判断时,可以使用示例查询(条件中没有主键)
Grade grade = new Grade();
grade.setName("计算机一班");
grade.setDesc("计算机科学与应用一班");
ct.add(Example.create(grade));
//分组聚合
ct.setProjection(Projections.rowCount());
ct.setProjection(Projections.groupProperty("gdesc"))
List<Grade> list = ct.list();
startDate,endDate
统计某个工人4月的班次
where startDate>=‘2014-4-1‘ and startDate<‘2014-5-1‘
统计某工人4月出现的所有班次
where endDate>=‘2014-4-1‘ and startDate<‘2014-5-1‘
命名HQL查询
1.在映射文件中添加query
<query name="loginUser">
<![CDATA[
from Login lo where lo.username=:username and lo.password=:password
]]>
</query>
2.代码中使用命名HQL查询
Query query = session.getNamedQuery("loginUser");
Login login = new Login();//创建查询模板
login.setUsername("马达");
login.setPassword("111111");
query.setProperties(login);
List<Login> list = query.list();
本地SQL查询
String sql = "select {l.*} from login l where l.username=‘马达‘";
SQLQuery query = session.createSQLQuery(sql).setEntity("l",Login.class);
List list = query.list();
命名SQL查询
1.在映射文件中添加sql-query
<sql-query name="findUser">
<![CDATA[
select {l.*} from Login l where l.username=?
]]>
<return alias="l" class="com.pb.Login"/>
</sql-query>
2.代码中使用命名SQL查询
Query query = session.getNamedQuery("findUser");
query.setString(0,"马达");
List<Login> list = query.list();
批量插入数据
1.在Hibernate.cfg.xml文件中,设置batch-size, use-second-level-cache;
2.在执行批量插入的循环中,添加判断,每二十个清空一次缓存,session.flush(),session.clear()
批量更新数据:
ScrollableResults result = session
.createQuery("from Login")
.scroll(ScrollMode.FORWARD_ONLY);
int count=0;
while(result.next()){
Login login = (Login)result.get(0);
login.setAge(21);
if(count%20==0){
session.flush();//强制数据库和持久状态的对象同步
session.clear();
}
count++;
}
tr.commit();
session.close();
执行存储过程:
CallableStatement call = session.connection().prepareCall("{call login_insert(?,?,?)}");
call.setString(1,"张三");
call.setString(2,"男");
call.setLong(3,21);
//执行增删改的存储过程
call.executeUpdate();
tr.commit();
session.close();
执行查询的存储过程
CallableStatement call = session.connection()
.prepareCall("{call login_query(?)}");
call.registerOutParameter(1, OracleTypes.CURSOR);
call.execute();
ResultSet rs = (ResultSet)call.getObject(1);
...
执行命名存储过程sql
<sql-query name="findUser" callable="true">
{call loginGetAll(?)}
<return alias="l" class="com.pb.Login"/>
</sql-query>
使用注解配置Hibernate映射
1.不需要配置映射文件
2.可以自动创建表
3.<mapping class="com.pb.Login"/>
4.创建sessionFactory时,使用的是AnnotationConfiguration
5.要添加三个jar包:
commons-logging-1.0.4.jar
hibernate-annotations.jar
hibernate-commons-annotations.jar
@Entity
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Basic
命名hql查询
@NamedQuery(name="命名hql查询",query="from Login")
命名本地查询
@NamedNativeQuery(
name="命名本地查询",
query="select * from login",
resultSetMapping="结果集映射名"
)
@SqlResultSetMapping(name="结果集映射名",entities={
@EntityResult(entityClass=Login.class,fields={
@FieldResult(name="id",column="ID")
})
})
Hibernate注解配置主外键关系
1.一对一
丈夫类/Husband:
@OneToOne(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn//这个注解只能写在主(生成ID)的一端
private Wife wife;
妻子类/Wife:
@OneToOne(cascade=CascadeType.ALL,mappedBy="wife")
private Husband husband;
2.一对多(多对一)
读者类/Reader:
@OneToMany(mappedBy="reader",cascade=CascadeType.ALL,fetch=FetchType.LAZY)
private Set<Book> books = new HashSet<Book>();
图书类/Book:
@ManyToOne(cascade=CascadeType.ALL,optional=false)
@JoinColumn(name="read_id",referencedColumnName="id")//外键为read_id,与Reader中的id关联
private Reader reader;
3.多对多
学生对课程:
学生类/Student:
@ManyToMany(targetEntity=com.hibernate.many2many.Course.class, cascade={CascadeType.MERGE,CascadeType.PERSIST})
@JoinTable(name="student_course",//中间表
joinColumns={@JoinColumn(name="student_id")},//中间表中对应学生表的外键
inverseJoinColumns={@JoinColumn(name="course_id")}//中间表中对应课程表的外键
)
private Set<Course> course;
课程类/Course:
@ManyToMany(targetEntity=com.hibernate.many2many.Student.class,
cascade={CascadeType.MERGE,CascadeType.PERSIST})
@JoinTable(name="student_course", //中间表
joinColumns={@JoinColumn(name="course_id")},//中间表中对应课程表的外键
inverseJoinColumns={@JoinColumn(name="student_id")}//中间表中对应学生表的外键
)
private Set<Student> student;