hibernate


第 1 章 Hibernate 入门
   1 Hibernate 的 优势
     简化了对数据库的操作,是建立在JDBC的基础上的。是对JDBC有丰富开发经验的人根据实际使用JDBC的经验,

     对JDBC操作进行了封装,Hibernate要求所有使用它的开发者,必须将数据库的链接信息房在一个配置文件中,

     这样不仅有利于项目的实施,而且降低了项目的风险,当数据库连接信息发生了变化,用户只需要修改配置
     文件信息就可以了。不用重新修改和编译源代码。


   2.Hibernate 的部署 (使用MyEclipse) 
     第一步: 右击项目 -- 选中MyEclipse -- Add Hibernate .....
     第二步: 上面选3.3  ,  中间三个全打钩 , 下面选copy到lib目录下
     第三步: 默认设置
     第四步:  数据库连接, 可以先不设置。 把钩取消了。
     第五步: 创建Hibernate工厂类。 输入包名。你要放入哪个包下面 。 一般为util
     第六步: 设置数据库连接与自动生成数据库表对应得实体类和配置文件(文件名.hbm.xml)。(生成的配置


文件数据类型比较坑。看情况改动) 
     设置连接之后要把jar包复制到lib目录去。
     


   3.配置文件大揭秘  --如下配置文件
 <hibernate-mapping>
    <class name="com.houserent.entity.Users" table="USERS" schema="HOUSERENT">
        <id name="id">
            <column name="ID"/>
            <generator class="sequence">
               <param name="sequence">SEQ_ID</param>
            </generator>
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" length="50" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="PASSWORD" length="50" />
        </property>
        <property name="username" type="java.lang.String">
            <column name="USERNAME" length="50" />
        </property>
    </class>
 </hibernate-mapping>
    
    class 节点 : 定义一个实体类的映射信息
       常用属性:name 表示对象实体类的全限定名 table表示对应得数据库表名
    id 节点: 该属性到数据库表的主键字段的映射
       常用属性:name 表示实体类属性的名字。 type 表示实体类属性的类型  column 表示数据库表字段的


名字,也可以在column节点中指定
    generator节点:对于主键的自动增长序列的生成策略
       常用属性和子元素:class 指定主键的具体生成策略 param 用来传递参数
       策略:class的指定值: 
            increment 对long . short int 以自动增长的方式生成主键值。 递增 1
            identity  对Sqlserver DB2 MySql 支持标识列的数据库主键自动增长,但数据库中必须设置为标


识列
            sequence  对Oracle DB2 等支持序列的数据库生成自动增长主键。 通过param传递序列名
            native     自动生成 不需要管
            assigned  暂未发现用处


    property节点: 定义实体类中属性和数据库表的字段的对应关系
       常用属性:name 表示实体类属性的名字
                 type 表示实体类属性的类型
                 column 表示数据库表字段的名字,也可以在column节点中指定
   
    column 节点: 用于指定父元素代表的实体类属性所对应的数据库表中的字段
       常用属性:name: 表示数据库字段的名字
                 length: 表示数据库字段的长度
                 not-null:true表示不能为空
 


    4.Hibernate 操作数据库 (简化方式)
    //增删改
    public void [对应操作的方法名](Object obj) {
Session session = null;


Transaction tx = null;


try {
                        //从工厂类中获取session
session = HibernateSessionFactory.getSession();
//开启事务
tx = session.beginTransaction();
                        //把对象保存进数据库。
//session.save(obj); 
                        //根据这个对象。来删除这条数据。
//session.delete(obj); 
                        //修改对应的这条数据
//session.update(obj); 


                        //提交事务
tx.commit();
} catch (Exception e) {
e.printStackTrace();
if (tx != null)
                                //如果有错误。就回滚
tx.rollback();
} finally {
                        //关闭session
session.close();
}
}


     //查询 参数1为id值。参数2为类的类型如:Student.class 。
     public Object get(Serializable key,Class clazz) {
Object result = null;

Session session = null;


Transaction tx = null;


try {
session = HibernateSessionFactory.getSession();


tx = session.beginTransaction();


result = session.get(clazz,key);


tx.commit();
} catch (Exception e) {
e.printStackTrace();
if (tx != null)
tx.rollback();
} finally {
session.close();
}
return result;
}


     5. Hibernate 中实体对象的三种状态
       瞬时状态:
          在使用持久化操作前, 实例化User对象。此时User对象并未与数据库中的数据有任何关系,这就是


瞬时状态,就是在内存中瞬时存在,与数据库记录无关
       持久状态:
          当使用Session的get或者load方法加载数据库中的一条记录的时候,返回的User对象时与数据库中一


条数据关联的。此时的User对象为持久状态
       游离状态:
          处于持久状态的对象,其对于的Session实例关闭后。User对象的各个属性的值与数据库中一条数据


的值是对应的。但是此时User对象并未受到Session实例的管理,所以此时User对象处于游离状态。


第 2 章 Hibernate 映射
     记住首先要把所有实体类的配置文件信息添加到 hibernate.cfg.xml的Mappings里面去
     1.在 hbm.xml的
       多对一配置: 
       如: 在街道实体类(street)中有这样一个区对象  。。 
        private District districtId;
       在配置文件中。
         <many-to-one class="com.houserent.entity.District" name="districtId">
         <column name="district_id"/>
         </many-to-one>
       配置文件值对应为:
         <many-to-one class="一方全限定名" name="多方对应的对象名">
         <column name="多方数据库表对应的字段名"/>
         </many-to-one>
      
      当你查询出一个街道的时候。 districtId的值, 就会自动有了。 就是街道对应的区对象!


     2.一对多配置:
      如:在区实体类(District)中有这样一个街道集合
       private Set<Street> streets = new HashSet<Street>();
      在配置文件中。
         <set cascade="all" name="streets" table="street" inverse="true">
           <key column="district_id"/>
         <one-to-many class="com.houserent.entity.Street"/>
         </set>
      配置文件对应为
         <set cascade="级联操作值" name="一方对应的对象名" table="多方数据库对应的表名" 


inverse="true">
           <key column="关联的外键名"/>
         <one-to-many class="多方的全限定名"/>
         </set>
      当你查询出一个区的时候。streets集合中,就会自动塞满所有属于这个区的街道
   
    小提示:单向一对多和多对一可以分别配置实用,如果同时配置了两者。那就是成了双向一对多关联。




      3.cascade属性 (级联操作)
        值:all  : 对所有操作进行级联操作
            save-update:保存和修改级联操作
            delete:删除操作级联
            none : 不进行级联。


      4.inverse 属性
       反转的意思。指定关联关系中的方向。inverse = "false"的为主动方。 主动方负责维护关联关系
       一对多关联中。 将one方设置 inverse = "true" 有助于性能的改善




      5.多对多配置。
      假如数据库有表:Student ,字段有: stu_id , stu_name    还有表:teacher 字段有:tea_id , 


tea_name  
      这是典型多对多。老师和学生。 自然的就会生成第三张表 :r_stu_tea  字段有:r_stu_id , r_tea_id


      Student实例类中有:private Set<Teacher> teachers = new HashSet<Teacher>();
      Teacher实体类中有:private Set<Student> students = new HashSet<Student>();


      在配置文件中。
         Student 方
         <class name= "Student" table = "Student">
           <set name="teachers" table="r_stu_tea" inverse="true">
             <key column="r_stu_id"/>
             <many-to-many class="entity.Teacher" column="r_tea_id"/>
           </set>
         </class>


         Teacher 方
         <class name= "Teacher" table = "Teacher">
           <set name="students" table="r_stu_tea">
             <key column="r_tea_id"/>
             <many-to-many class="entity.Student" column = "r_stu_id"/>
           </set>
         </class>


第 3 章 HQL实用技术
  1.使用HQL
    第一步:得到Session 
    第二步:编写HQL语句
    第三步:创建Query对象
    第四步:执行查询,得到结果


    以下代码所示:
        //hql语句
        String hql = "from House";
Session session = null;
try {
       //得到session
session = HibernateSessionFactory.getSession();
//创建Query对象
Query query = session.createQuery(hql);
//执行查询,得到结果.
List<House> list = query.list();
for(House h : list){
System.out.println(h.getTitle());

System.out.println(h.getDescription());
}
} catch (Exception e) {
e.printStackTrace();
}finally{
session.close();
}


   2.实体查询
     hql是种面向对象的查询语言,所以要注意的是。在配置好配置文件之后。 
     hql语句 "from House" 的House是指实体类名, 而不是数据库表名,严格区分大小写。
     如果House存在子类,那么子类的数据也会全部查出来。即时子类对应不同表。


   3.属性查询
     String hql = "select u.name from House u";
     只查询单个值。
   4.参数绑定
     4.1 "?"占位符
        与JDBC的?占位符类似。
给?占位符填值有些不一样。 使用Query对象的 setXxx方法填值。 注意下标从0开始,
而JDBC是从1开始的


代码案例:
String hql = "from Users where name = ?";
对应。
query.setString(0, userName);
     
     4.2 命名参数
        通过 :名字  的方式定义占位符 然后用query对象的setXxx方法赋值


代码案例:
String hql = "from Users where name = :name";
对应。
query.setString("name", userName);
 
     4.3 封装参数
        查询条件很多的情况下。可以把条件封装成一个Bean,然后通过Query对象的setProperties方法实现参


数设定


代码案例:
Bean类 有很多查询条件 。 全部封装在这里
类名比如为:QueryBean
private Integer typeId;
private String title;
private Integer min_price;
private Integer max_price;
private Integer min_floorage;
private Integer max_floorage;
private Integer streetId;
--省略
//很多查询条件。 语句很长
String hql = "from House t where type_id = :typeId and street_id = :streetId  and (price 


between :min_price and :max_price) and (floorage between :min_floorage and :max_floorage)";
        //放入一下查询条件bean类的实例。就可以了。如果一个一个设置。那会很长。你懂的。
        query.setProperties(new QueryBean(参数省略));


     5.聚合函数
       //其他的聚合函数如 max , min , avg , sum  和sql一致
       String hql="select count(u) from Users u"; 
     6.排序
       //与sql 一致
       String hql="from Users u order by u.id";
     7.分组
       //查询租房面积大于1000的街道的数量
       String hql = "select sum(house.floorage) from House house guoup by house.street_id having 


sum(house.floorage)>1000"
     8.分页
       hql实现分页非常简单。通过设置query对象的setFirstResult()方法和setMaxResult()方法就可以实现


了。
       代码案例:
       String hql = "from House";
Session session = null;
try {
session = HibernateSessionFactory.getSession();
Query query = session.createQuery(hql);
//page为当前页,pageSize为每页显示的数量.setFirstResult方法参数1意思为,从


第几行开始读取
query.setFirstResult((page-1)*pageSize);
//setMaxResults方法参数1意思为,每次读取数据的行数
query.setMaxResults(pageSize);
List<House> list = query.list();
以下省略
                 如pageSize 为5 page为1   那么就是从第 (1-1)*5行 开始,取5条数据 取出 01234
如pageSize 为5 page为2   那么就是从第 (2-1)*5行 开始,取5条数据 取出 56789


      9.子查询
        与sql 一样。 如下代码案例:
查询价格大于 平均价格的房屋
select * from House as h1 where h1.price>(select avg(h2.price) from House h2)


第 4 章 HQL进阶
  1.HQL优化
    1.1 避免or操作
        很多情况下,如果where子句中包含or操作,那么执行将不使用索引,某些环境下可以用in替换
    
    1.2 避免使用not
        如果where子句条件包含not关键字,那么执行时该字段的索引无效,
    
    1.3 避免like的特殊形式
        如果like以 % 或者 _ 开始,那么该字段索引不起作用
   
    1.4 避免having子句
        尽可能在where指定条件而不是在having中指定
 
    1.5 避免使用distinct
        指定 distinct 会导致在结果中删除重复的行,这对处理时间会造成一定影响当允许冗余的时候,应该


避免使用它


  2.数据加载方式
    2.1 即时加载
        当实体加载完成后,立即加载其关联数据, 比如 District 配置文件中对应的字段设置 lazy="false"
那么就是即时加载,当加载Street的时候,立刻就加载了它对应的District对象,
即时加载的基本原理,就是当数据加载时,Hibernate会自动加载其关联的数据。, 


    2.2 延迟加载
        延迟加载机制是避免一些无谓的性能开销提出来的。延迟加载就是当你真正需要数据的时候,才执行
数据加载操作。
2.2.1 集合延迟加载
  比如District对象有个Street的set集合,将set元素设置lazy = "true" ,那么。当获取District
  对象的时候,集合不会立即加载,而当你去获取这个集合的时候,才会发送语句。获取数据,性能
  大幅提高。


2.2.2 实体对象延迟加载
   给class设置 lazy = "true" 就是当获取一个对象出来的时候,并不会发生语句查询这个对象的数


据。
   而当你使用的时候。就会去查询数据了。
   3. list() 和 iterate()
        3.1 list()和iterate()的区别
   1.使用list()方法获取查询结果,每次发出一条查询语句,获取全部的数据    
   2.使用iterate()方法获取查询结果。先发送一条语句获取所有满足条件的id,
   然后根据id查询记录,也就是要执行 N+1条sql语句,(N为符合条件的记录数)


   3.list()方法将不会在缓存中读取数据,它总是一次性的从数据库中直接查询
   出所有符合条件的数据,同时将数据写入缓存
   4.使用iterate()方法获取查询结果。先发送一条语句获取所有满足条件的id,
   然后根据id在缓存中查询符合条件的数据,若无符合条件的数据,再到数据库查询
  
   4. HQL联接查询
      只有5种查询方式:内连接,迫切内连接,左外连接,迫切左外连接,右外连接
         left right   fetch
        4.1 内联接:inner join
代码案例: from District d inner join fetch d.streets s
sql中使用on 联接对应的关系,在Hibernate中已经由映射文件制定,因此不需要了


       fetch 加了这个关键字就是迫切连接了。当查询出District的数据的时候,自动会
       把查出来对应的Street的数据塞入到District的集合中,
       如果不使用fetch关键字,那么就不会喔。


   5. 命名查询
       就是把查询语句 放到 配置文件中, 与class节点同级, 以<![CDATA[HQL]]>的方式
       保存语句, 代码如下所示:
       User类的配置文件中 写入
       <query name = "findUsers">
         <![CDATA[from User]]>
       </query>


       在代码中 。 使用 Query query = session.getNamedQuery("findUsers");
       来获取该查询语句。


    6. 本地sql查询
       hql虽然强大, 但不能覆盖所有的查询特性。有的时候还是要用到sql语句。
       如下sql 语句:
       select {u.*} from users u
       其中,u是别名,{}表示引用实体的属性,在实例中,使用{u.*} 标记所有属性。
       执行本地sql查询使用 SQLQuery接口。 还需要配置addEntity(别名,实体类)方法一起使用。代码如下:
       session.createSQLQuery(sql).addEntity("u",User.class);   u是语句中表的别名
       
       可以查询多个 {u.*}{d.*}  那么 addEntity方法就要连续调用了


       如果配合命名查询,那么在配置文件中 。
       <sql-query name = "findUsers">
         <![CDATA[select {u.*} from user]]>
<return alias = "u" class="entity.User">
       </sql-query>
       return 节点,表示配置对应的实体类。alias表示别名。class是全限定名


第 5 章 Criteria查询
   Criteria查询使用面向对象的方式封装查询条件,即时对sql语句不了解,也可以进行查询。
   
   1.Criteria查询使用方式
     1.1代码案例:
       Criteria criteria = session.createCriteria(User.class); //传入实体类
       List result = criteria.list();   //直接就可以获得User对应的数据表的所有数据


     1.2 带条件查询
       Criteria criteria = session.createCriteria(User.class); //传入实体类
       criteria.add(Restrictions.eq("name","admin"));  //查询name为admin的数据, 添加Restrictions,
       参数1为判断哪个字段,参数2为判断的值
       List result = criteria.list();   


   2.Restrictions常用的查询方法
       Restrictions.eq()   对应sql的等于 =
       Restrictions.allEq() 使用Map,使用key/value进行多个对等值得对比
       Restrictions.gt()   对应sql的 >
       Restrictions.ge()   对应sql的 >=
       Restrictions.lt()   对应sql的<
       Restrictions.le()   对应sql的<=
       Restrictions.between()  对应sql的 between
       Restrictions.like()   对应sql的like
       Restrictions.in()  对应sql的 in
       Restrictions.and() 对应sql的 and
       Restrictions.or()  对应sql的or
       Restrictions.not() 对应sql的 not


   3.使用Example
     如果属性条件很多,以上方法就不方便了,如果已经有一个对象,那就可以根据这个对象作为查询的依据



     查询出属性与之类似的对象,如现有租金为1500元,面积为75的房屋对象,查询出与之类似的数据。
     支持等于喔。很多方面不支持
     代码案例:
        House h =new House();
h.setPrice(1500d);
h.setFloorage(75);
        //省略获得session代码。
        Criteria criteria = session.createCriteria(User.class); //传入实体类
criteria.add(Example.create(h));
        List result = criteria.list();   //直接就可以获得User对应的数据表的所有数据
  
   4.Criteria查询排序
      Criteria对象.addOrder(Order.desc("Price"));  //根据价格降序
      Criteria对象.addOrder(Order.asc("Price"));  //根据价格升序


   5.Criteria查询限定返回数据行数和分页
      Criteria对象的setMaxResults() 方法可以限定查询返回数据的行数,
      配合Criteria对象的setFirstResult()设定查询返回结果的第一行数据的位置,
      就可以实现分页了
      代码案例:
      Criteria对象.setMaxResults((page-1)*5);  //page就是当前页。 是1的话, 那就是从第0条开始 , 


取到第4条数据
      Criteria对象.setFirstResult(5);            是2个话, 就是从第5条数据开始, 取到第9条数据
 
   Projections


第 6 章 Filter 过滤器
    1. 过滤器的执行过程。
       配置了Filter过滤器之后。在运行某个Servlet的时候就会先运行Filter。然后再去运行Servlet
       ,先执行init() , 然后执行 Filter()
    2. 配置Filter 的配置信息
在web.xml里面配置Filter
<filter>
 <filter-name>TestFilter</filter-name>           //filter的名称
 <filter-class>filter.TestFilter</filter-class>  //对应的filter类的全限定名
 <init-param>                                    //初始化参数
  <param-name>encoding</param-name>           
  <param-value>UTF-8</param-value>
 </init-param>
</filter>
<filter-mapping>                                //filter映射
 <filter-name>TestFilter</filter-name>          //对应的filter的名称
 <url-pattern>/FindServlet</url-pattern>        //这个filter所作用的范围。这里的意思就是


这个TestFilter作用于FindServlet
</filter-mapping>                               如果用 /* 的话。 就是作用全部Servlet。
 
     3. 编写Filter类
        package filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class TestFilter implements Filter{    //需要实现Filter接口。
private String encoding = null;       //字符编码
public void destroy() {               //销毁的时候调用此方法。
System.out.println("销毁");
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {  //处理


请求
System.out.println("执行编码");
request.setCharacterEncoding(encoding);   //设置编码格式、
chain.doFilter(request, response);       //把请求发送到下一个Filter或者


Servlet
}
public void init(FilterConfig config) throws ServletException {
    System.out.println("执行初始化");
    encoding = config.getInitParameter("encoding");  //获取初始化参数值。
}
}


第 8 章 PL/SQL
   1.PL/SQL
     答:PL/SQL是一种复杂的程序设计语言,它将第四代语言的强大功能和灵活性与第三代语言
     的过程结构的优势有效的结合在一起,除了支持所有的对数据库操作的sql语句外,
     同样还支持动态sql,能够动态执行sql语句定义,数据控制和会话控制语句。
   2.PL/SQL语句块
     declare    变量声明部分
     begin      语句块开始部分
     end        结束部分


   3.变量和常量
     declare 变量名 [constant] 变量类型 [not null] [:=值]
     其中 declare 表示声明;
     constant表示是否是常量,可选。
     not null 表示变量不能为空,可选
     最后的表示赋初始值, 可以先不赋值。


     代码案例:
       declare   //变量声明块开始
         v_a int := 10;
v_b int := 20;
     
     命名规则为:变量名长度不超30字符,变量名不能有空格,变量名首字符必须是英文字符,
     其后可以是字母,数字或者字符$,#,_
   
   4.条件结构
     4.1  if then 结构
     代码案例:
       if (10 > 2) then
dbms_output.put_line('10大于2');  //输出语句
       end if;    //记得用分号结束


     4.2  if then else 结构
     代码案例:
       if (10 > 2) then
dbms_output.put_line('10大于2');  //输出语句
       else 
         dbms_output.put_line('2大于10');  //输出语句
       end if;    //记得用分号结束


     4.3  if then elsif 结构 相当于 java多重if 
          if (v_age < 10) then
   dbms_output.put_line('年龄<10!!!');
 elsif (v_age >= 10 and v_age < 20) then
   dbms_output.put_line('v_age >= 10 and v_age < 20');
 else
   dbms_output.put_line('v_age >= 20 !!!');
 end if;
        注意:是elsif  不是elseif  这里少了个e
     
     4.4 case 语句
      代码案例:  
           --相当于一个switch
 case v_sex                //判断条件。 如果v_sex 值为0 , 那么输出 男 否则输出女
   when 0 then
     dbms_output.put_line('男');
   else
     dbms_output.put_line('女');
 end case;


 --相当于一个多重if
 case                      //可以先不设定
   when (v_age < 10) then            
     dbms_output.put_line('年龄<10!!!');
   when (v_age >= 10 and v_age < 20) then
     dbms_output.put_line('v_age >= 10 and v_age < 20');
   else
     dbms_output.put_line('v_age >= 20 !!!');
 end case;


   5.循环结构
     5.1  LOOP END LOOP 结构。
     LOOP
    v_count := v_count + 1;
    dbms_output.put_line(v_count);
    IF v_count >= 10 THEN    
      EXIT;           //使用EXIT退出。 不退出会死循环
    END IF;       //注意分号
     END LOOP;   //注意分号


     5.2  while LOOP END LOOP 结构
     //while循环, 首先判断循环条件再进入。进入后条件不满足的时候退出。 
     WHILE (v_count <= 10) LOOP
      v_count := v_count + 1;
      dbms_output.put_line(v_count);
     END LOOP;


     5.3 for LOOP END LOOP 
      --for循环,可选的reverse来反转循环变量,循环变量可以不声明直接使用
      FOR i IN  1 .. 10 LOOP      // i为循环变量, 1 .. 10 就是从1到10  循环10次
       dbms_output.put_line(i);
      END LOOP;


   6.动态SQL  
     可以把sql语句作为字符串进行运行
     
     6.1 执行ddl
      begin
        execute immediate 'create table ..省略';
      end


     6.2 绑定变量
      declare
        plsql varchar2(200);
t_name varchar2(20);
        t_id integer:='1002';
begin
 plsql :='insert into temp_table values(:1,:2)';   //:1 ,1为占位符名,
 execute immdiate plsql using t_id,t_name;  //传递两个参数填充进去
end;


     6.3 获取回调值 returning into
        //演示了获取动态sql执行后的回调值
declare
 v_id   number;
 v_name varchar2(20);
 v_age  number;
 v_str  varchar2(200);
begin
--:xx表示占位符,returning子句后的占位符相当于输出占位符,需要用变量来接收输出的内容
 v_str := 'update  temp_table set name=''孙武空'' 
where id=:1 returning id,name into :t2,:t3';


 execute immediate v_str
   using 1
   returning into v_id, v_name;
 commit;
 dbms_output.put_line('编号:' || v_id || ',姓名:' || v_name);
end;


   7.异常处理
     代码案例:
declare 
   v_age number := 20;
   myException exception;   //声明异常myException
begin
    if(v_age=50) then
raise myException;    // raise 触发异常
    elsif v_age=40 then
dbms_output.put_line('40男人一枝花');
    else
dbms_output.put_line('顶呱呱'); 
    end if;
       dbms_output.put_line('年龄合适');
exception                     //处理异常
    when myException then    //处理异常 
 dbms_output.put_line('年龄太大了');
end;


   8.游标
     8.1游标的属性
     %FOUND    描述:用于检测游标是否成功,当查出一条数据的时候返还True
     %ISOPEN   描述:用于判断游标是否被打开。如果视图打开一个已经打开或关闭的游标,将出现错误
     %NOTFOUND 描述:与%FOUND相反
     %ROWCOUNT 描述:循环执行游标读取数据的时候,返还检索出的记录行数的总数
     总结:%看起来怪怪的 ,可以想象成. 如:游标对象.rowcount, 游标对象%rowcount ,别扭只是习惯问题


     8.2游标的使用
       1.声明游标 
         cursor 游标名 [参数列表 ,可选的][返还值 返还值类型  可选的] is 查询语句
代码案例如下:


       2. 显示游标示例
declare
 v_name district.name%type;
 v_districttype district%rowtype; --定义一个对应表的行类型
 cursor d_cursor is select * from district where id=1000;  //1.声明游标
begin
    --2.打开游标
    open d_cursor;
    
    --3.抓取游标内容 给 v_districttype变量;
    fetch d_cursor into v_districttype;
    
    dbms_output.put_line(v_districttype.name||v_districttype.id);
    //4.关闭游标
    close d_cursor;  
end;
        3. 游标循环提取
  只写for循环的读取方式。其他的循环的读取方式 。太少用。不建议用.不好用
  --循环游标--for
declare
 cursor d_cursor is select * from district;  //声明游标
begin            
    --for循环遍历游标,隐式打开和关闭游标
    for t_district in d_cursor  
    loop
dbms_output.put_line(t_district.name||t_district.id);
    end loop;
  end;


第 9 章 Oracle数据库对象
   1.过程
     1.1简介:过程是为了只学一定的任务,实现特定的功能,是将sql或者pl/sql代码集中在一起的代码语句


集合,
     过程包括声明部分,执行部分,异常处理部分,过程一般被设计成求若干个运算结果,完成一系列的数据


处理
     语法:create [or replace] procedure 过程名             --中括号[] 里面的表示可有可无
        [(参数列表)] as begin 过程体 end                    --or replace表示如果存在此名称的过程,


则覆盖
     1.2代码案例:
     create or replace procedure InserCar     --创建过程
(v_carId [in|out|in out] varchar2,      --参数列表 , 中间如果不写,默认是in输入参数,
v_carType [in|out|in out] varchar2,     也可以是out输出参数和in out
v_carPrice [in|out|in out] number,
v_carNewDate [in|out|in out] date,
v_carExhaust [in|out|in out] number
) as 
[declare]  --声明变量部分可有可无,声明变量
begin   --过程体
 insert into store_car values (v_carId, v_carType, v_carPrice, v_carNewDate, 


v_carExhaust);
 commit;
end; 


     1.3调用过程:   只用在begin  end 里面调用就可以了
         declare
 v_carId varchar2(20) :='89759';
 begin
 InserCar(v_carId,'宝马',50,sysdate,5);
 end;
    
     1.4删除过程:
         drop procedure 过程名
    
   2.函数
     2.1简介:与过程类似,函数与过程最大的区别在于,函数最终任务是返回一个表示结果的值,
              另外函数的调用是表达式的一部分,而过程的调用本身就是一条pl/sql语句


     语法:create [or replace] function 函数名             --中括号[] 里面的表示可有可无
        [(参数列表)] return 返回的数据类型 as begin 过程体 end  --or replace表示如果存在此名称的过


程,则覆盖
     
     2.2代码案例:
     create function addCar(
  v_carid  varchar2,
  v_cartype  varchar2,
  v_carprice  number,
  v_carnewdate date,
  v_carexhaust  number
) return number as        -- 必须声明返回的数据类型
 --这里如果要声明变量,直接声明就可以了 不需要declare了,这是函数的特点
begin
 insert into store_car values (v_carid, v_cartype, v_carprice, v_carnewdate, 


v_carexhaust);
 commit;
 return 1;     --必须返回值
 end;


     2.3调用函数: 用法和系统函数类似。自己体会, 必须max()函数,min()函数等等
         declare
  co number;
begin
 --必须接收或者查询返回值。否则报错
  co:=addCar('88888','奔驰',500,sysdate,40);
 end;
    
     2.4删除函数:
         drop function 函数名;
    
   3.过程和函数的比较
     1.标示符不同,函数一般不采用变量形参,
     2.函数名运行完直接return函数值。而过程的返回值必须使用变量形参返回。
     3.不能给过程名赋值。也不能定义过程类型,但是函数可以有类型,并可以将函数值传递给函数名。
     4.函数在定义时一定要定义函数的类型说明,过程不用。
     5.函数的调用出现在表达式中。而过程有独立的过程调用语句来完成。
     6.过程一般被设计成求若干个运算结果,完成一系列的数据处理,而函数值为了求一个函数
   4.Oracle中的包
     简介:包分为两部分,包头和包体,包头就是包的规范,类似于接口。而包体类似于实现类。
           里面可以有函数和过程,变量等。
     4.1 包头的创建
        语法:
--注意! 包头和包体要分开执行。否则会出现错误!
create or replace package 包名 as 
  包规范,可以有函数,过程,变量等等
end 包名;
        代码案例:
create or replace package car_package as  
 function addCar(   --定义过程,不需要create了。类似接口,包体必须实现。
  v_carid  varchar2,
  v_cartype  varchar2,
  v_carprice  number,
  v_carnewdate date,
  v_carexhaust  number
) return number;


procedure InserCar   --定义函数,不需要create了,类似接口,包体必须实现。
(v_carId in varchar2,
v_carType in varchar2,
v_carPrice in number,
v_carNewDate in date,
v_carExhaust in number
);
end car_package;


     4.2 包体的创建  
         --注意! 包头和包体要分开执行。否则会出现错误!
         语法:
create or replace package body 包名 as    --多了body
  实现包头里的所有东西,
end 包名;
代码案例:
         create or replace package body car_package as
 function addCar(     --上例过程的实现
    v_carid  varchar2,
    v_cartype  varchar2,
    v_carprice  number,
    v_carnewdate date,
    v_carexhaust  number
 ) return number as   -- 必须声明返回类型sss
 begin 
   insert into store_car values (v_carid, v_cartype, v_carprice, v_carnewdate, 


v_carexhaust);
   commit;
   return 1;
   end addCar;   --结束这个过程
   
 procedure InserCar    --上例函数的实现
 (v_carId in varchar2,
  v_carType in varchar2,
  v_carPrice in number,
  v_carNewDate in date,
  v_carExhaust in number
 ) is 
 begin
   insert into store_car values (v_carId, v_carType, v_carPrice, v_carNewDate, 


v_carExhaust);
   commit;yh                         
   end InserCar;
end car_package; --结束这个函数
     4.3 包的调用
        就根据上例进行调用,直接用 包名. 就可以了
declare
  co number;
begin
 --必须接收或者查询返回值。否则报错
  co:=car_package.addCar('88888','奔驰1',500,sysdate,40);
  car_package.InserCar('89759','宝马1',50,sysdate,5);
 end;
   5.视图
     5.1简介:
       视图简单来说就是一张虚拟的表,是经过查询操作后形成的一个结果。其输出形式类似一个表。
       视图是对一个真实表的引用、  不能对数据进行修改
     5.2创建:
       create or replace view 视图名 as 
       查询语句 [with check option] --with..表示进行插入或者修改的数据记录必须满足视图定义的约束
       代码案例:
         create view view_student as 
         select stu_name,stu_age from student
     5.3查询:
         select * from 视图名
     5.4删除:
         drop view 视图名
     5.5权限问题:
         创建视图需要创建视图的权限,必须赋予这个用户权限。
--用dba权限给lesson9用户创建视图的权限
         grant create any view to 用户名;  --给需要创建视图的用户赋予权限
   6.序列
     简介:
       序列是用来生成一系列唯一数据的数据库对象,可以实现自增的效果。
     创建:
       create sequence 序列名
       start with 1   -- 设置种子为1
       increnment by 1  --设置每次递增1,负数为递减
       [maxvalue 数字] --设置序列最大值
       [minvalue 数字] --设置最小值
     修改:
       alter sequence 序列名        --不能修改种子数了.
       increnment by 1  --设置每次递增1,负数为递减
       [maxvalue 数字] --设置序列最大值
       [minvalue 数字] --设置最小值
     删除:
       drop sequence 序列名
     使用:
       序列名.nextval  返回下个一值。
       序列名.currval  返回当前值
   7.数据库链
     简介:
       Database link 能够实现从一个数据库实例访问到另外一个数据库实例(可以是本地或者远程)
     创建:
       create database link link_sales     --数据库链的名称为link_sales
       connect to sales identified by sales  --对方数据库的登录名和密码。
       using '(description = 
          (address_list = (address = (protocol = tcp)(host = 127.0.0.1)(port = 1521)) --host的值为


ip地址。
          )
          (connect_data = (service_name = sales))   --service_name的值为目标的数据库实例名
       )';
     
     访问:
      select * from seles@link_sales   --查询seles表的时候,后面跟上数据库链的名字




第 10章 提高数据库性能
   1.索引: 之前有很多索引的资料了。不多做介绍了
     创建:create [unique] index 索引名 on 表名(列名)
   2.表分区:
     简介:增强数据库的可用性,分区了,一部分分区出了问题,。只用修复这一部分。
         减少维护工作量,均衡IO,提高查询效率,分区对用户保持透明,就是把表的数据
放在几个磁盘的几个表空间中。  
     2.1 范围分区(Range)
       语法:
       partition by range(stu_result)(   --范围分区操作stu_result为要分区的字段
         partition 分区名 values less than(范围) tablespace 表空间名
       )
       代码案例:
       --创建分区表
create table score     --创建表,注意分区要和创建表一起运行。
(
  stu_no number primary key,
  stu_name varchar2(20) not null,
  subject varchar2(20) not null,
  stu_result number not null
)partition by range(stu_result)(   --范围分区操作,根据学生成绩分区
   partition d_p1 values less than(60) tablespace dp1,   --60以下的分到dp1这个区
   partition d_p2 values less than(80) tablespace dp2,   --60-80的分到dp2这个区
   partition d_p3 values less than(maxvalue) tablespace dp3  --80以上分到dp1这个区,


maxvalue表示到最大值
);
     
     2.2 列表分区(List)
       与范围分区相比,列表分区是枚举的,一般适合低基数列
       语法:
       partition by list(列名)(
          partition 分区名 values (值) tablespace 分区名
       )


       代码案例:
       create table student(
          stu_name varchar2(20),
 stu_sex varchar2(4)
       )partition by list(stu_sex)(
          partition man values ('男') tablespace dp1,   --把所有男同胞放到dp1,女同伴放到dp2
 partition man values ('女') tablespace dp2
       )
     2.3 散列分区(hash)
        是在列取值很难确定的情况下使用的一种分区方式。平均分配下来。数据的分配由
Oracle分配。
        代码案例:
create table movie1(
  m_id number primary key,
  playdate date not null,
  statu varchar2(10) not null,
  m_name varchar(20),
  m_state varchar2(20)
)
partition by hash(m_state)(  --根据日期散列分区。
 partition part_1 tablespace s1,   --part_1为分区名  s1为表空间名
 partition part_2 tablespace s2,
 partition part_3 tablespace s3
)
     2.4 索引分区
        2.4.1 本地索引分区
代码案例:
create table score
(
  stu_no number primary key,
  stu_name varchar2(20) not null,
  subject varchar2(20) not null,
  stu_result number not null
)partition by range(stu_result)(   --范围分区操作
   partition d_p1 values less than(60) tablespace dp1,
   partition d_p2 values less than(80) tablespace dp2,
   partition d_p3 values less than(maxvalue) tablespace dp3
);
create index result_index on score(stu_result) local( --创建本地索引 score表的stu_result


字段
   partition d_p1 tablespace dp1,
   partition d_p2 tablespace dp2,
   partition d_p3 tablespace dp3
);
2.4.2 全局索引分区
create index g_index on score(stu_result)   --在范围分区的stu_result字段的基础上加上了全局


索引
global partition by range(stu_result)(   --范围分区操作,根据学生成绩分区
   partition d_p1 values less than(60) tablespace dp1,   --60以下的分到dp1这个区
   partition d_p2 values less than(80) tablespace dp2,   --60-80的分到dp2这个区
   partition d_p3 values less than(maxvalue) tablespace dp3  --80以上分到dp1这个区,


maxvalue表示到最大值
);


课外扩展:
   oracle实现任意数字的阶乘
  阶乘指从1乘以2乘以3乘以4一直乘到所要求的数。例如所要求的数是4,
  则阶乘式是1×2×3×4,得到的积是24,24就是4的阶乘。 例如所要求的数是6,
  则阶乘式是1×2×3×……×6,得到的积是720,720就是6的阶乘。例如所要求的数是n,
  则阶乘式是1×2×3×……×n,设得到的积是x,x就是n的阶乘。任何大于1的自然数n阶乘表示方法:
  n!=1×2×3×……×n  或 n!=n×(n-1)!   5!=5*4*3*2*1=120。


create or replace function fun_n_jc (i in number)
return number
is
n number:=1;
Begin
 for c in 1..i loop          -- loop到传递过来的参数值
   n:=n*c;
 end loop;
 return n;
end;


declare 
numb number;
begin
 numb:= fun_n_jc(3);
 dbms_output.put_line(numb);
 end;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值