黑马程序员技术交流社区

标题: 【石家庄校区】hibernate知识库 [打印本页]

作者: zhangxuchang    时间: 2018-6-27 15:16
标题: 【石家庄校区】hibernate知识库
本帖最后由 小石姐姐 于 2018-6-29 11:09 编辑

hibernate知识库
环境搭建
1.导入jar包
    1.导入相关jar包
        拷贝hibernate-release-5.0.7.Final目录下lib/required目录下所有jar包
    2.导入数据库驱动jar包
    3.导入日志相关jar包
        log4j-1.2.16.jar
        slf4j-api-1.6.1.jar
        slf4j-log4j12-1.7.2.jar
    4.拷贝hibernate-release-5.0.7.Final\lib\optional\c3p0下所有jar包  
        c3p0-0.9.2.1.jar
        hibernate-c3p0-5.0.7.Final.jar
        mchange-commons-java-0.2.3.4.jar   
    5.将hibernate-release-5.0.7.Final目录下project/etc/log4j.properties文件拷贝到工程src目录下
2.提供核心配置文件 hibernate.cfg.xml  (src目录下)
3.映射配置文件  类名.hbm.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-configuration>
    <session-factory>
        <!-- 配置关于数据库连接的四个项 driverClass url username password -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql:///hibernateTest</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">abc</property>
        <!-- 设置连接提供者 -->
        <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
        <!-- c3p0连接池的配置 -->
        <property name="hibernate.c3p0.max_size">20</property> <!-- 最大连接池 -->
        <property name="hibernate.c3p0.min_size">5</property> <!-- 最小连接数 -->
        <property name="hibernate.c3p0.timeout">120</property> <!-- 超时 -->
        <property name="hibernate.c3p0.idle_test_period">3000</property> <!-- 空闲连接 -->
        <!-- 可以将向数据库发送的sql显示出来 -->
        <property name="hibernate.show_sql">true</property>
        <!-- 格式化sql -->
        <property name="hibernate.format_sql">true</property>
        <!-- hibernate的方言 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- 自动创建表 -->
        <property name="hibernate.hbm2ddl.auto">update</property>
        <!-- 用于设置事务提交方式 -->
        <property name="hibernate.connection.autocommit">false</property>
        <!-- 配置hibernate的映射文件所在位置 -->
        <mapping resource="cn/itheima/domain/Customer.hbm.xml" />
    </session-factory>
</hibernate-configuration>

配置映射文件
<?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">
<!-- package属性代表javabean所在的包 -->
<hibernate-mapping>
            <!--
                name    实体类的全名
                table   表的名称
                catalog 数据库名称
            -->
        <class name="com.b3a4a.domain.Customer" table="t_customer" catalog="db_hibernate_study">                 
                <!--id它是用于描述主键
                    name      实体类中那个属性对应的是主键
                    column    数据库表中哪一列是主键-->               
                <id name="id" column="id">
                    <!-- 主键生成策略 -->
                    <generator class="native"></generator>
                </id>   
                <!--使用property来描述属性与字段的对应关系
                    name   实体类中的属性
                    column 实体类中属性对应数据库表中的列
                    length 该列的长度限制-->      
                <property name="name" column="name" length="20" type="string"></property>
                <property name="address" column="address" length="50"></property>
                <property name="sex" column="sex" length="20"></property>
                字符串一定给length    type可以不写
        </class>
</hibernate-mapping>
执行原理
1.通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件
2.由bibernaate.cfg.xml中的
<mapping resource="cn/itheima/domain/Customer.hbm.xml"/>读取解析映射文件
3.通过config.buildSessionFactory();得到sessionFactory
4.sessionFactory.openSession();得到session
5.session.beginTransaction();开启事务
6.具体业务操作
7.session.getTransaction().commit;提交事务(update insert delete)
8.关闭session  session.close();
9.关闭session  sessionFactory.close();一般不关闭
hibrenate api
1.Configuration         加载hibernate.cfg.xml核心配置
2.SessionFactory        接口, 创建Session对象, 不是轻量级的不关闭
3.Session               接口, 非线程安全,与数据库CRUD,save/update/delete
4.Transaction           事务接口, 管理事务
5.Query                 接口, 查询操作 HQL/SQL
6.Criteria              接口, 面向对象标准化查询, 轻量级
详解
获得session:
    1.sessionFactory.openSession();
    这种方式获取的session不能被手动关闭, 不必再写session.close()
    2.sessionFactory.getCurrentSession();
    这种方式获得session每次都是新的,前提是本地线程绑定session
    即在cfg.xml配置了<property name="hibernate.current_session_context_class">thread</property>
   
Session常用方法:
    save/update/delete
    get/load  根据id进行查询
    saveOrUpdate   执行save或update操作
    createQuery()  获取Query对象
    createSQLQuery()  获取一个可以操作sql的SQLQuery对象
    createCriteria()  获取一个Criteria 查询操作
   
Transaction:
    commit  事务提交
    rollback 回滚
    session.beginTransaction();  开启事务, 获得Transaction对象
    如果程序没有开启事务, 是否存在事务?
        有事务, session的每一个操作就会开启一个事务.
        
Query:
    session.createQuery(hql);
    session.createSQLQuery(sql);

Query查询操作Hibernate注解开发
在hibernate中我们使用注解,可以帮助我们简化伙伴们文件配置
PO类注解配置
@Entity 声明一个实体
@Table来米哦啊书类与表对应
@Table(name="t_book",catalog="hibernateTest")
public calss Book{
@Id 来声明一个主键
@GenerateValue 用它来声明一个主键生成策略

//@GeneratedValue //native
@GeneratedValue(strategy = GenerationType.IDENTITY) //identiy
默认情况下相当于native
可以选择的主键生成策略 AUTO IDENTITY SEQUENCE@Column 来定义列

@Column(name="c_name",length=30,nullable=true)
注意:对于PO类中所有属性,如果你不写注释,默认情况下也会在表中生成对应的列,列的名称就是属性的名称。
@Temporal来声明日期类型

@Etmporal(TemporalType.TIMESTAMP) //是用来定义日期类型
private Date publicationDate;  //出版日期
可以选择
TemporalType.DATAY 只有年月日
TemporalType.TIME 只有小时分钟秒
TemporalType.TIMESTAMP  有年月日小时分钟秒
@Type:可允许你去指定Hibernate里面的一些类型

@Type(type="double") //允许你去指定Hibernate里面的一些类型
private Double price;//价格,如果没有添加注解,也会自动的生成在表中
编写完上述Book实体类之后,千万不要忘记下面这一步,我们最终需要在hibernate.cfg.xml 文件中将我们类中的注解配置引用生效
<mapping class="cn.itheima.domain.Book"/>
问题:1.如果我们主键生成策略想使用UUID类型?
@Id

@GenericGenerator(name=“myuuid”,strategy="uuid")

@GeneratedVAlue(generator="myuuid")

private String id;
问题2:如果设定类的属性不在表中映射?

@Transient

private String msg; // 现在这个属性不想生成在表中
对于我们以上讲解的关于属性配置id注解,我们也可以在其对一个的getxxx方法去使用

一对多(多对一)
@OneToMany
​        一对多:
​        rargetEntity: 多的一方类型
​        mappedBy:放弃外键维护
​        orphanRemoval:删除孤儿
@ManyToOne
​                多对一:
​                rargetEntity:一的一方的类型
以Customer与Order为例
客户(Customer) 类

@OneToMany(targetEntity=Order.class,mappedBy="c")

private Set<Order> orders = new HashSet<Order>();
订单(Order) 类

@ManyToOne(targetEntity=Customer.class)

@JoinColumn(name="c_customer_id")//指定外键列

private Customer c; //描述订单属于一个客户
示例:保存客户时,保存订单
对于这个示例我们需要在Customer中配置cascade操作,save-update
第一种方式,可以使用 JPA 提供的注解

@OneToMany(targetEntity=Order.class,mappedBy="c",cascade=CascadeType.ALL)
private Set<Order> orders = new HashSet<Order>();
第二种方式:可以使用hibernate提供的注解
@OneMany(targetEntity=Order.class,mappedBy="c")
@Cascade(CascadeType.SAVE_UPDATE)
private Set<Order> orders=new HashSet<Order>();
下面是示例代码

//3.建立关系
c.getOrders().add(o1);
c.getOrders().add(02);
//4.保存客户,并级联保存订单
session.save(c);
订单中没有关联客户的id,为什么?
原因:我们在Customer中配置了mappedBy=“c”它代表的是外键的维护由Order方来维护,而Customer不维护,这时你在保存客户时,级联保存订单,是可以的,但是不能维护外键,所以,我们必须在代码中添加订单与客户关系。
多对多
@Cascade配置级联:
​                CascadeType.xxx

一对一
@OneToOne 声明一对一外键映射(主键映射了解)

检索方式
导航对象图检索方式,根据已加载的对象导航到其他对象
OID检索方式,按照对象的OID来检索对象(get/load)
HQL检索方式,使用面向对象的HQL插叙语句
QBC检索方式,使用QBC(Query  by Criteria)API来检索对象,这种API封装了基于字符串形式的查询语句,提供了更加米面向对象的查询接口:

基本检索:
Criteria criteria=session.createCriteria(Customer.class);
List<Customer>list=criteria.list();

排序检索:
cruteria.addOrder(org.hibernate.criteriion.Order.asc("money"));//升序

条件检索:
Restrictions.xxx()eq and or like get it....

分页检索:
criteria.setFirstResult(2-1)*6);
criteria.setMaxResults(6);

统计检索:
criteria.setProjection( projections.projectionList().add(Projections.sum("money")).add(Projections.groupProperty("c")));

离线条件检索:
​        DetachedCriteria dc=DetachedCriteria.forClass(Customer.class);不借助于session web
​        Criteria criteria=dc.getExecutableCriteria(session);dao
本地SQL检索方式,使用本地数据库的SQL查询语句

Hibernate-day04先来说明一件问题演示sql多表操作

再就是hql的多表操作,hql的迫切连接很重要,但是在sql中是没有的
Hibernate事务管理(非常重要,面试必问)事务介绍事务提交方式

<!-- 用于设置事务提交方式 -->
<property name="hibernate.connection.autocommit">false</property>在Hibernate中设置事务管理级别

Hibernate中session的管理,Hibernate提供了三种管理session的方式:
Hibernate优化方案HQL优化1.使用参数绑定2.尽量少使用NOT3.尽量使用where来替换having4.减少对表的查询5.使用表的别名6.实体的更新与删除一级缓存优化注解配置抓取策略set上的fetch与lazy1.查询所有
    使用HQL

2.分页查询
    query.setFirstResult(10);
    query.setMaxResult(10);

3.查询指定列信息****(查询属性)

    和HQL投影检索一样
    先要在Customer实体类生成name,address的有参构造,并加无参构造.
    select new Customer(name,address) from Customer;
    将属性封装到对象中

4.条件查询
    from Customer where name=?
    query.setParameter(0,"张三")      对参数进行赋值, hql是从0开始的
    如果查询结果是唯一的, query.uniqueResult();

5.执行本地SQL
    sqlQuery=session.createSQLQuery("select*from t_customer");
    把查询到的sql语句结果封装到Customer对象中
    sqlQuery.addEntity(Customer.class);
    如果sql中有参数, 使用setParameter()方法完成参数传递

6.Criteria:
    适合多条件查询
    criteria.add(Restrictions.eq("name","xxx"));
    查询姓名为张三或者address为上海
    criteria.add(Restrictions.or(Restrictions.eq("name","张三"),Restrictions.eq("address","上海")));






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2