1】了解hibernate框架,首先了解crm,即客户管理系统,对企业的销售,营销,服务等各阶段的客户信息和客户活动进行管理。其具体功能如下:
客户信息管理、联系人管理、客户访问管理,综合查询,统计分析,系统管理。
2】crm三层技术架构:表示层(视图+控制 即jsp、html、servlet)、业务层(service)持久层(将数据持久化到数据库以及一些接口)。
3】hibernate属于轻量级持久层框架,用于实现DAO,是一个关系型数据库ORM框架。用于实现DAO:用hibernate实现对数据库的访问。
ORM:object ralation mapping 对象关系映射
4】hibernate项目准备:
1、导包
2、建表
3、创建配置文件X.hbm.xml(配置数据库表和pojo属性的对应关系,主键信息等)和X.java(对应数据库中的表中字段)的pojo文件。
public class CstCustomer implements java.io.Serializable {
private Long custId;
private String custName;
private Long custUserId;
private Long custCreateId;
private String custSource;
private String custIndustry;
private String custLevel;
private String custLinkman;
private String custPhone;
private String custMobile;
public Long getCustId() {
return custId;
}
public void setCustId(Long custId) {
this.custId = custId;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public Long getCustUserId() {
return custUserId;
}
public void setCustUserId(Long custUserId) {
this.custUserId = custUserId;
}
public Long getCustCreateId() {
return custCreateId;
}
public void setCustCreateId(Long custCreateId) {
this.custCreateId = custCreateId;
}
public String getCustSource() {
return custSource;
}
public void setCustSource(String custSource) {
this.custSource = custSource;
}
public String getCustIndustry() {
return custIndustry;
}
public void setCustIndustry(String custIndustry) {
this.custIndustry = custIndustry;
}
public String getCustLevel() {
return custLevel;
}
public void setCustLevel(String custLevel) {
this.custLevel = custLevel;
}
public String getCustLinkman() {
return custLinkman;
}
public void setCustLinkman(String custLinkman) {
this.custLinkman = custLinkman;
}
public String getCustPhone() {
return custPhone;
}
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
public String getCustMobile() {
return custMobile;
}
public void setCustMobile(String custMobile) {
this.custMobile = custMobile;
}
}
4、创建hibernate.cfg.xml文件,里面配置访问数据库的信息,如驱动,数据库,数据库账号密码,及加载X.hbm.xml文件。
<hibernate-configuration>
<!-- 配置会话工厂所需要的属性 -->
<session-factory>
<!-- 配置hibernate运行的参数 -->
<!-- 数据库方言,根据数据库选择 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 数据库驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 数据库连接url -->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernateproject</property>
<!-- 数据库用户名和密码 -->
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
<!-- 配置c3p0 -->
<!-- 连接池提供商 -->
<property name="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
<!-- 连接池中保留的最大连接数-->
<property name="hibernate.c3p0.max_size">10</property>
<!-- 连接池中保留的最小连接数 -->
<property name="hibernate.c3p0.min_size">1</property>
<!-- 最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃 -->
<property name="hibernate.c3p0.maxIdleTime">60</property>
<!-- 获得连接的超时时间,如果超过这个时间,会抛出异常,单位毫秒 -->
<property name="hibernate.c3p0.timeout">5000</property>
<!--为了方便调试是否在运行hibernate时在日志中输出sql语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 是否对日志中输出的sql语句进行格式化 -->
<property name="hibernate.format_sql">true</property>
<!--
hbm2ddl.auto的4个值,如果不需要设置为none,建议正式环境设置为none
validate 加载hibernate时,验证创建数据库表结构
create 每次加载hibernate,重新创建数据库表结构,这就是导致数据库表数据丢失的原因。
create-drop 加载hibernate时创建,退出是删除表结构
update 加载hibernate自动更新数据库结构
none 不执行检查
-->
<property name="hibernate.hbm2ddl.auto">none</property>
<!-- 加载hbm.xml映射文件 -->
<mapping resource="cn/itcast/crm/domain/CstCustomer.hbm.xml"/>
</session-factory>
5】hibernate执行流程:
应用程序
1、 configuration hibernate配置文件(hibernate.cfg.xml--->X.hbm.xml---->X.java)
2 、Sessionfactory会话工厂(线程安全,采用单例模式创建)
3、Session会话
4、Transaction事务管理对象(回滚事务、提交事务),其中进行query查询操作不需要开启事务,增删改操作需要。
5、 访问到数据库
6、 释放资源
6】hibernateUtil工具类
public class HibernateUtil {
// 会话工厂,以单例方式管理
private static SessionFactory sessionFactory;
// ThreadLocal存储session
private static ThreadLocal<Session> session = new ThreadLocal<Session>();
// 以单例方式管理sessionFactory
static {
try {
sessionFactory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
} catch (HibernateException e) {
e.printStackTrace();
throw new HibernateException("初始化会话工厂失败!");
}
}
//得到一个单例的会话工厂
public static SessionFactory getSessionFactory(){
return sessionFactory;
}
//获取一个新session
public static Session openSession(){
return sessionFactory.openSession();
}
//获取当前与线程绑定的session,如果获取不到则创建一个新session并与当前线程绑定
// public static Session getCurrentSession() throws HibernateException {
// //获取当前线程绑定的session
// Session s = (Session) session.get();
// if (s == null) {
// //创建一个新session
// s = sessionFactory.openSession();
// //新session并与当前线程绑定
// session.set(s);
// }
// return s;
// }
public static Session getCurrentSession() throws HibernateException {
return sessionFactory.getCurrentSession();
}
//关闭当前线程绑定的session
// public static void closeSession() throws HibernateException {
// //获取当前线程绑定的session
// Session s = (Session) session.get();
// if (s != null){
// //关闭session
// s.close();
// }
// session.set(null);
// }
public static void closeSession() throws HibernateException {
sessionFactory.getCurrentSession().close();
}
}
7】客户列表查询
1、QBC(query by criteria)按条件查询。
public Long findCustomerCount(CstCustomer cstCustomer) {
Session session = HibernateUtil.openSession();
Criteria criteria = session.createCriteria(CstCustomer.class);
criteria.setProjection(Projections.rowCount());
//查询总数
Long total = (Long) criteria.uniqueResult();
return total;
}
2、离线的criteria即DetachedCriteria,其创建不需要session,但必须通过session变为criteria才能执行操作,建议使用detachedcriteria。
public Long findCustomerCount(DetachedCriteria detachedCriteria){
Session session = HibernateUtil.openSession();
//离线criteria与session绑定生成可执行criteria
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
criteria.setProjection(Projections.rowCount());
//查询总数
Long total = (Long) criteria.uniqueResult();
return total;
}
public List<CstCustomer> findCustomerList(DetachedCriteria detachedCriteria, int firstResult, int maxResults){
Session session = HibernateUtil.openSession();
//离线criteria与session绑定生成可执行criteri
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
criteria.setFirstResult(firstResult);
criteria.setMaxResults(maxResults);
List list = criteria.list();
return list;
}
8】hibernate对象的三种状态
1、瞬时态(创建对象时为瞬时态,没与session绑定,无主键值,瞬时态设置主键值便变为托管态)
2、持久态(瞬时态对象执行save之后变为持久态,与session关联),持久态对象可直接设置属性,并在数据库更改。持久态执行delete方法后转为瞬时态。
3、托管态(持久态对象关闭session后变为托管态,有主键值),托管态执行updata或saveorupdata方法时转为持久态。
9】一级缓存
对象执行save,对象保存在一级缓存中。
一级缓存是 session对象中一块内存。
在同一个session中,查询一个对象是不会发出sql语句。
session关闭一级缓存不存在了,再查询对象,会发出sql。
10】客户和联系人的增删改查,配置:
一个客户有多个联系人,客户到联系人为一对多关系。
一个联系人只有属于一个客户,联系人到客户多对一关系。
客户方配置:
联系人方配置:
1、双方同时添加
2、已有客户,只添加联系人
方法:通过客户持久态对象添加联系人
错误:持久态对象引用了一个舜时态对象
object references an unsaved transient instance - save the transient instance
解决:commit之前将瞬时态转成持久态,使用hibernate级联保存方法解决。
在CstCustomer.hbm.xml中配置cascade:
报错:
Column 'lkm_cust_id' cannot be null
执行向联系人表插入时,'lkm_cust_id字段设置了一个空值。
解决方法:
观察控制台,打出一条多条的sql:
上边打出多余sql的原因,当前一对多、多对一的关系由一方来维护的。
解决方法:让关系的维护方变为多方。