ssh

来源:互联网 发布:银联数据应届生待遇 编辑:程序博客网 时间:2024/06/18 09:56

Hibernate :
1、框架是什么?
用来提高开发效率的
将一些功能封装好,需要这些功能时,调用即可,不需要在手动实现
可以理解为是一个半成品的项目,只要懂得驾驭这些功能即可

2、Hibernate框架。
主要用于dao层的数据库操作、(由sturts2操作web层,spring统筹三层)
操作数据库的时候,可以以面向对象的方式来完成.不需要书写SQL语句
Hibernate是一款orm框架,(orm对象关系映射,依靠配置文件,将数据库表与javabean的对象映射起来,理想状况下实现面向对象的方式操作数据库 )

3.hibernate框架搭建的基本步骤:
1.导包。(lib下的required为必导包,以及数据库驱动包)
2、创建数据库,准备实体,准备表(可以由hibernate自动生成)
3、书写orm元数据。(完成对象与表的映射配置文件 以 .hbm.xml作为文件后缀)
a、导入约束 b 创建实体 c orm元数据
4、书写主配置文件 (默认文件名为 hibernate.cfg.xml 放在src 目录下)
a、五个必写配置 (以sql server数据库为例)
数据库驱动
<property name="hibernate.connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>

数据库url
<property name="hibernate.connection.url">jdbc:sqlserver://localhost:1433;DatabaseName=server01</property>

数据库连接用户名
<property name="hibernate.connection.username">sa</property>

数据库连接密码
<property name="hibernate.connection.password">123456</property>

数据库方言
不同的数据库中,sql语法略有区别. 指定方言可以让hibernate框架在生成sql语句时.针对数据库的方言生成.
sql99标准: DDL 定义语言 库表的增删改查
DCL 控制语言 事务 权限
DML 操纵语言 增删改查
注意: 不知道选哪个就选最短的吧

 `<property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>`    b、三个可选配置 <!-- 将hibernate生成的sql语句打印到控制台 --><property name="hibernate.show_sql">true</property><!-- 将hibernate生成的sql语句格式化(语法缩进) --><property name="hibernate.format_sql">true</property><!--     ## auto schema export  自动导出表结构. 自动建表    #hibernate.hbm2ddl.auto create      自动建表.每次框架运行都会创建新的表.以前表将会被覆盖,表数据会丢失.(开发环境中测试使用)    #hibernate.hbm2ddl.auto create-drop 自动建表.每次框架运行结束都会将所有表删除.(开发环境中测试使用)    #hibernate.hbm2ddl.auto update(推荐使用) 自动生成表.如果已经存在不会再生成.如果表有变动.自动更新表(不会删除任何数据).    #hibernate.hbm2ddl.auto validate    校验.不自动生成表.每次启动会校验数据库中表是否正确.校验失败.     -->     <!--   在一般开发中选择适当的数据库生成方法,一般使用update就行  -->    <property name="hibernate.hbm2ddl.auto">update</property>C、元数据引入配置    <!-- 引入orm元数据        路径书写: 填写src下的路径,注意在路径中 使用斜杠" / "而不是 class 中的 " . "     --><mapping resource="cn/itheima/domain/Customer.hbm.xml" />

5、元数据的配置
在mapping中加入package属性 可以在下面的配置中省略包名

<hibernate-mapping package="cn.xxx.domain" >
class元素: 配置实体与表的对应关系的            name: 完整类名            table:数据库表名    <class name="Customer" table="cst_customer" >        <!-- id元素:配置主键映射的属性                name: 填写主键对应属性名                column(可选): 填写表中的主键列名.默认值:列名会默认使用属性名                type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.                        每个类型有三种填法: java类型|hibernate类型|数据库类型                not-null(可选):配置该属性(列)是否不能为空. 默认值:false                length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度            <id name="cust_id"  >                 generator:主键生成策略(每个数据库不同,建议用native 使用默认数据库的 生成策略)                 <generator class="native"></generator>            </id>            property元素:除id之外的普通属性映射                    name: 填写属性名                    column(可选): 填写列名,不填的话默认name属性值                    type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.                            每个类型有三种填法: java类型|hibernate类型|数据库类型                    not-null(可选):配置该属性(列)是否不能为空. 默认值:false                    length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度             -->            <property name="cust_name" column="cust_name" >                <!--  <column name="cust_name" sql-type="varchar" ></column> -->            </property>            <property name="cust_source" column="cust_source" ></property>            <property name="cust_mobile"></property>          </class>    </hibernate-mapping>

hibernate api:
1、Configuration 读取主配置文件、建议封装起来只一个工程创建一次
2、SessionFactory 读取元数据,读取后在数据库建表,用于获取打开 session 的工厂
3、session 与用户交流的会话

public void fun1(){    //1、创建Configuration ,加载主配置·,默认路径    Configuration conf = new Configuration().configure();    //2.根据配置信息创建 SessionFactory     SessionFactory sessionFactory = conf.buildSessionFactory();    //3.获取一次会话    Session session = sessionFactory.openSession();    //4.获得并  打开事务    Transaction tx = session.beginTransaction();    //---------------CURD操作------------------------    Customer c = new Customer();    c.setCust_name("google公司");    session.save(c);//执行保存    //----------------------------------------------    tx.commit(); //tx.rollback(); 回滚    session.close();      sessionFactory.close();

===========================================

hibernate中的实体规则
1、注意事项:
需要提供无参构造
提供set/get方法(有set/get才算是一个属性)
应使用包装类型(可以有null这个值) 要有与主键对应的属性不应该直接使用与对象有关的属性做主键
不要用final修饰class
2、主键类型、主键生成规则。
自然主键(不建议使用):业务对象中有符合主键要求的属性
应该用代理主键(与对象无关的)

    生成规则:        sequence: Oracle中的主键生成策略.        native: hilo+sequence+identity 自动三选一策略.        hilo(了解): 高低位算法.主键自增.由hibernate来维护.开发时不使用.        uuid: 产生随机字符串作为主键. 主键类型必须为string 类型.        assigned:自然主键生成策略. hibernate不会管理主键值.由开发人员自己录入.

hibernate的对象状态:
根据有没有id 以及在缓存中的状态分为
瞬时状态; 没有id
持久化状态;有id有 session缓存
游离状态: 有ID 没有色双死哦in缓存

hibernate的一级缓存和快照(提高数据效率)
hibernate 在获取session对象然后与数据库交流前会查看一级缓存中是否有对应id,
如果没有则生成SQL语句查询数据库,然后返回到hibernate一级缓存中,同时在快照中存一份,在session没有关闭前如果 有下一条语句则会在缓存和快照中查找是否有对应的 对象ID 如果有则在缓存中更改,最后关闭才执行SQL到数据库。(提交事务后,缓存会与快照中的对象比较,没有变化就不执行sql)

hibernate的事务处理
事务的特性:a 原子性 c 一致性 i 隔离性 d 持久性
并发的主要问题; 脏读 不可重复读 幻、虚读
事务的隔离级别(严格性从小到大):读未提交 1 读已提交 2 可重复读 4 串行化 8 (通过设置配置文件制定隔离级别,整合spring后建议不要使用防止以spring冲突!)
4

hibernate 管理事务:
1、在servic业务开始前打开事务,业务执行之后提交事务,出现异常就回滚
2、dao层操作的session对象应该与servic层的session对应是同一个才能保证事务安全性。
3、hibernate中有get.CurrentSession()方法获取当前线程的session对象
(在servic层new 一个session对象,然后再调用DAO层的方法时,该方法用get.CurrentSession()获取该线程对象)
要设置主配置才能使用hibernate的get.CurrentSession()保证事务安全 , 在整合spring后此配置由spring负责
thread
4、注意,在使用get.xxx方法获取session对象时,当事务提交时 不需要手动调用close关闭,

hibernate的批量查询
1、HQL查询:hibernate query language(不复杂可以使用)
Hibernate独家查询语言,属于面向对象的查询语言
基本查询: save(user),delete() ,update()
2、Criteria查询:(hibernate 的查询方法)

=========================================
多表关系(在hibernate中要体现多表需要在实体类、配置文件中加入表间关系的语法)

一对多和多对一的 元数据配置:
O (对象): 一的一方使用集合. 多的一方直接引用一的一方.
在一的一方实体中加入集合属性,存放多的一方对象
private Set linkMens = new HashSet();
//在多的一方加入对象属性
private Customer customer ; //Customer为 一 的对象
R (关系型数据库):多的一方使用外键引用一的一方主键.
M (映射文件) 一对多的配置:



    <!-- 映射文件示例:        lazy属性: 决定是否延迟加载            true(默认值): 延迟加载,懒加载            false: 立即加载            extra: 极其懒惰        fetch属性: 决定加载策略.使用什么类型的sql语句加载集合数据            select(默认值): 单表查询加载            join: 使用多表查询加载集合            subselect:使用子查询加载集合     -->    <!-- batch-size: 抓取集合的数量为3.        抓取客户的集合时,一次抓取几个客户的联系人集合.    -->        <set name="linkMens" batch-size="3"  >            <key column="lkm_cust_id" ></key>            <one-to-many class="LinkMan" />        </set>    多: <many-to-one name="" column="" class="" />      //name:  column:在多一方的表中加入的外键。class:一 的类    <!-- 映射文件示例:        fetch 决定加载的sql语句            select: 使用单表查询            join : 多表查询        lazy  决定加载时机            false: 立即加载            proxy: 由customer的类级别加载策略决定.     -->    <many-to-one name="customer" column="lkm_cust_id" class="Customer" fetch="join" lazy="proxy"  >    </many-to-one>操作: 操作管理级别属性.     cascade: 级联操作   (在set标签中)        减少我们书写的操作代码.        none(默认值)   不级联        save-update:    级联保存(建议使用)        delete:         级联删除        all:            级联保存+级联删除    inverse: 反转关系维护    (为了维持表间关系而存在,在一的一方放弃维护这样可以删除多一方的数据)        属于性能优化.关系的两端如果都书写了关系.那么两方都会发送维护关系的语句.        这样,语句就发生重复.我们可以使用inverse使一的一方放弃维护关系.        true            放弃        false(默认值)  维护    结论: 在一对多中,一的一方可以放弃维护关系.多对多中必须有一方放弃维护!

多对多的关系
O 对象 两方都使用集合.
R 关系型数据库 使用中间表.至少两列.作为外键引用两张表的主键.
M 映射文件

<set name="集合名" table="中间表名" >      <key column="别人引用我id" />            <man-to-many class="别人的类" column="我引用别人的id" /></set>

在配置多对多关系的时候注意 维护外键关系只需要一个表设置即可,
使用inverse属性
true: 放弃维护外键关系
false(默认值):维护关系

<set name="teachers" table="student_Teacher" inverse="true">        <key column="sid" ></key>        <many-to-many class="Teacher" column="tid" ></many-to-many></set>

结论: 将来在开发中,如果遇到多对多关系.一定要选择一方放弃维护关系.
一般谁来放弃要看业务方向. 例如录入员工时,需要为员工指定所属角色.
那么业务方向就是由员工维护角色. 角色不需要维护与员工关系.角色放弃维护

操作:操作管理级别属性. ..    cascade: 级联操作           减少我们书写的操作代码.        none(默认值)   不级联        save-update:    级联保存        delete:         级联删除        all:            级联保存+级联删除    结论: 可以使用save-update.不推荐使用delete. 也可以不用cascade.    inverse: 反转关系维护        属于性能优化.必须选择一方放弃维护主键关系.哪方放弃要看业务方向.   

===========================================================================
hibernate 查询总结和 加载 关联

oid查询:根据id查询==get(xxx.class,1l);
对象属性导航:getlist
HQL语法: 面向对象语句查询
//获取整个实体对象
String hql = “from xx实体类” (查询整个对象)
String hql2 = “from java.lang.Object”;
Query query = session.createQuery(hql);
List list = query.list();

//排序语法
String hql = “from xx实体” Order by 字段 desc /asc
//条件查询
String hql = “from xx实体” where id=? ;
Query query = session.createQuery(hql);
query.setParameter(1,8);
//分页查询(mysql中 用 limit ?,?)
setFirstResult(?);
setMax
//统计查询(聚合函数)
String hql=”select count(*)/avg(id)/sum()/min(id)/max()/ from xxx”
Query query = session.createQuery(hql);
Number number = (Number)query.uniqueResult();

//投影查询(查询一个属性)
String hql = “select xx_name from xx实体类” ;
Query query = session.createQuery(hql);
List list = query.list();
//多表查询
内连接 String hql = “from A inner join a.linkMens”;(linkMens为外键列)
Query query = session.createQuery(hql);
List list = query.list();
迫切内连接:
String hql = “from A inner join fetch a.linkMens”;(linkMens为外键列)
List list = query.list();
外连接
左外
String hql = “from A left inner join a.linkMens”;
右外
String hql = “from A right inner join a.linkMens”;

Criteria查询:
//基本查询:
A a = session.createCriteria(A.class);
List list = a.list(); //放在所有条件后面

//条件查询 直接add添加条件(Restrictions.xx)
a.add(Restrictions.ideq(1)); //查询id为1

//分页查询
a.setFirstResult(0);//第一页
a.setMaxResult(2); // 前两条

//排序
a.addOrder(Order.asc(id/字段))
a.addOrder(Order.desc(id/字段))

//统计查询
Number num = a.setProjection(Prjections.聚合函数);

//离线查询
criteria 创建依赖于session
session.createCriteria();

在Servic层 DerachedCriteria dc = DatachedCriteria.forClass(Customer.class);dc.add(Restrictions.adEq(1)); //拼装条件  与Criteria 一致Criteria c = dc.getExecutable(session);List  list = c.list();

查询优化
类级别查询
懒加载/延迟加载:在打印对象时有$符号,则该对象为代理对象
get方法立即加载,session.get(A.class,2l);
load方法延迟加载,返回一个对象,该对象使用时才执行sql获得该对象
session.load(A.class,2l);
load方法的延迟加载属性,可以在配置class时,加 lazy属性,默认为turn,false为不延迟

关联级别查询 &  属性抓取策略(  为了提高效率,用lazy属性和fetch属性,达到查询关联的    效果,在一对多或多对多、多表查询中 通过一个对象,获取与之关联的其它对象) 获取的一个对象,在获取与之关联的对象或对象集合 (get方法)    LinkMan lm = session.get(LinkMan.class, 3l);    Customer customer = lm.getCustomer(); <!-- 映射文件示例:    lazy属性: 决定是否延迟加载        true(默认值): 延迟加载,懒加载(对象在使用时才加载)        false: 立即加载        extra: 极其懒惰    fetch属性: 决定加载策略.使用什么类型的sql语句加载集合数据        select(默认值): 单表查询加载        join: 使用多表查询加载集合        subselect:使用子查询加载集合 --> <many-to-one name="customer" column="lkm_cust_id" class="Customer"         fetch="(默认select)" lazy="(默认true)"  ></many-to-one>    <!-- batch-size: 抓取集合的数量为3.        抓取客户的集合时,一次抓取几个客户的联系人集合.    -->    <set name="linkMens" batch-size="3"  >        <key column="lkm_cust_id" ></key>        <one-to-many class="LinkMan" />    </set>

原生sql查询 :
String sql = “select * from A”; //sql语句
SQLQuery query = session.createSQLQuery(sql); //创建一个查询

a.add(Restrictions.ideq(1)); //add添加条件(Restrictions.xx) 查询id为1List<Object[]> list = query.list();  

==========================================================================

原创粉丝点击