12月12日——培训第20天

田老师总算是回来了,好啊……前两天张老师的课把我都给整晕了,笔记也是乱七八糟……现在终于能够正常一些,系统一些了

上午课程开始:

今天继续讲解HQL,课件上还引入了QBC的概念,Hibernate的东西已经有点遗忘了……糟糕了。

田老师的NETMeeting出问题了,没办法只好使用李春辉的netmeeting作为主持会议了,还好还可以使用……
今天上午的课程主要是HQL,下午要把从oracle到现在的内容全部回顾一下,免得遗忘,
周四来了会先复习HTML、JavaScript和DOM,如何使用PowerDesigner设计数据库ER图,P/SQL存储过程,
Oracle数据管理等,然后才是进入JavaWeb部分。

Hibernate今天的课只是讲完了基础,还有关系、集合等等高级内容

-----------------------------------------
session.load方法需要主键,然而并不是所有情况都知道主键

Hibernate中有以下几种查询机制:
OID(Object Identifier):使用Session.load或session.get只能加载一个对像,必须知道主键
HQL(Hibernate Qurey Language):面向对象的查询语言,需要使用字符串来定义语句。
QBC(Query By Criteria):以编程方式实现查询,不需要使用字符串形式的查询语言
QBE(Query By Example):按样例查询
SQL:纯SQL形式


HQL语法接近SQL,并且大小写不敏感,具备面向对象语言特性,有继承、多态等等。是从一类对象中查询,
不是查表。

例如:
session = factory.getCurrentSession();
session.beginTransaction();

Query q = session.createQuery("from java.lang.Object"); //这样就是从所有的已经被映射过的并且继承自Object
              //类的类实例中选取!这就是所谓的继承特性了
List l = q.list();
Iterator it = l.iterator();
while(it.hasNext())
{
 User u = (User)it.next();
 System.out.println(u.getUsername());
}

注意:还可以这么写:Iterator it = q.iterate();
那么q.list().iterator()和q.iterate()有什么区别呢??
q.iterate()执行过程:先找到主键,然后根据主键一次次的执行sql语句把记录
一条条的都取出来;

q.list.iterator():一次性的读入所有数据,然后再迭代

如果不确定有多少条记录的话,最好不用q.list.iterator();否则内存可能吃不消;
假如每读入一条记录的话,都要对其进行复杂的处理的话,这种情况应该使用q.iterate()
方法,当然iterate()方法最麻烦的是要一直保持连接……

最好的办法是使用q.list.iterator()实现分页功能,10条10条的取,这样最好。
例如:
Query q = session.createQuery("from User").setFirstResult(m).setMaxResults(n);
//这代表从m条记录开始,一次读取n条记录!

Iterator it = q.list().iterator();

然后循环迭代就生成了类似select * from users where limit(m,n);这就是mysql的分页语句;
如果把dielect对应换成Oracle、或是SQLServer的话,只要show_sql属性为true的话,执行
后你都可以看到对应的分页语句在各个数据库中是如何实现的

如果我希望每n条记录打印出来后,需要我敲打回车才能够继续向下显示的话,应该如何去作呢?
注意每次变的是第一次开始的那个值,也就是FirstResult中的值

而且要知道一共有多少条记录:
------------------------
真正的实现分页读取的代码如下:


Query q = session.createQuery(select count(*) from User);
Integer total = (Integer)q.uniqueResult();  //返回总记录,由于该方法返回的是对象,所以用包装类包装一下。

int first = 0

while(first<total.intValue())
{
 q  = session.createQuery("from User").setFirstResult(first).setMaxResults(2);
 Iterator it = q.list().iterator();
 while(it.hasNext())
 {
  User u = (User)it.next();
  System.out.println(u.getUsername() + "、");
 }
 first += 2 ;
 new BufferedReader(new InputStreamReader(System.in)).readLine();//等待控制台读入一行
}

System.out.println("程序结束!");

上面的代码针对所有的数据库都可以使用
----------------------------
1 让HQL语句执行的方式有哪些呢?
list()方法;iterate()方法;uniqueResult()方法

list()返回List(如果返回ArrayList的话需要强制类型转换)、
iterate()方法返回iterator、
uniqueResult()方法返回Object(使用的时候肯定需要强制类型转换)
scroll()方法返回可滚动的结果集,用法上这个可以滚动的结果集和jdbc中的一样
-----------------------------
老师上课写的分页代码:


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import vo.User;

public class Demo {

 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub

  SessionFactory factory = new Configuration()
    .addResource("User.hbm.xml").buildSessionFactory();

  Session session = null;

  try {
   BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
   session = factory.getCurrentSession();
   session.beginTransaction();

   Query q = session.createQuery("select count(*) from User");
   Integer total = (Integer) q.uniqueResult();

   int first = 0;

   while (first < total.intValue()) {
    q = session.createQuery("from User")
         .setFirstResult(first)
         .setMaxResults(2);

    ArrayList l = (ArrayList)q.list();
    Iterator it = l.iterator();
    while (it.hasNext()) {
     User u = (User) it.next();
     System.out.println(u.getUsername() + "、");
    }
    first += 2;
    reader.readLine();
   }
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

}
---------------------------------------
下面的代码用来告诉我们如果选取的是两个字段的话,那么如何进行迭代的问题
Query q = session.createQuery("select id, username,password from User");//注意这里如果不加上
           //包名.User的话,那么必须加上auto-import属性!!        
List l = q.list()
Iterator it = l.iterator();
while(it.hasNext())
{
 Object[] obj = (Object[])it.next();
 Integer id = (Integer)obj[0];
 String username = (String)obj[1];
 String password = (String)obj[2];
 System.out.println(id + " "+username+" "+password);
}

session.getTransaction().commit();
-------------------------
当然还有一种写法,可以不用这个Object数组,而用list
//注意下面的new list不能换为new set,因为username和password可能是相等的,
//如果替换为new map的话是可以的,map可以存重复的值(只要键不同就行)
Query q = session.createQuery("select new list(id, username,password) from User");
List l = q.list()
Iterator it = l.iterator();
while(it.hasNext())
{
 List obj = (List)it.next();
 Integer id = (Integer)obj.get(0);
 String username = (String)obj.get(1);
 String password = (String)obj.get(2);
 System.out.println(id + " "+username+" "+password);
}

session.getTransaction().commit();
---------------------------
如果换成map的话,有三种方法
Query q = session.createQuery("select new map(id, username,password) from User");
List l = q.list();
Iterator it = l.iterator();
while(it.hasNext())
{
 Map obj = (Map)it.next();
 Set keys = obj.entrySet();
 Iterator it1 = keys.iterator();
 while(it1.hasNext())
 {
  Map.Entry entry = (Map.Entry)it1.next();
  System.out.print(entry.getKey() + " " + entry.getValue());
 }
 
}

session.getTransaction().commit();

或者:

Query q = session.createQuery("select new map(id, username,password) from User");
List l = q.list();
Iterator it = l.iterator();

while(it.hasNext())
{
 Map obj = (Map)it.next();
 System.out.println(obj.get("0") + " " + obj.get("1") + " " + obj.get("2")); 
}

或者:


Query q = session.createQuery("select new map(id as id, username as name,password as pw) from User");
List l = q.list();
Iterator it = l.iterator();

while(it.hasNext())
{
 Map obj = (Map)it.next();
 System.out.println(obj.get("id") + " " + obj.get("name") + " " + obj.get("pw")); 
}
----------------------------
也可以不用集合类,自己定义一个新的实体类。

public class UserProxy
{
 private int id ;
 private String name ;
 private String pw ;
 public UserProxy(int id,String name,String pw)
 {
  this.id = id ;
  this.name = name ;
  this.pw = pw ;
 }
 然后是三个属性的getter和setter方法,略……
};

注意User前面之所以不用加包名,是因为在配置文件中配置了auto-import属性,但是UserProxy是你自己
创建的类,但是不是已经被映射过的实体类,所以包名绝对不可以省略!
只有在映射文件中已经被映射的实体类才可以在HQL语句字符串中不加包名!!

Query q = session.createQuery("select new 包名.UserProxy(id , username,password) from User");
List l = q.list();
Iterator it = l.iterator();

while(it.hasNext())
{
 UserProxy obj = (UserProxy)it.next();
 System.out.println(obj.getId,obj.getName,obj.getPw); 
}
--------------------------------------------------------
所以如果不是选择整个对象,而是选择对象的几个属性的话:
1 如果是单一属性,返回的类型和属性原来的类型是一致的
2 如果是多个属性,默认情况下会返回Object[],
  如果假如list/map则返回java.util.List/java.util.Map
  也可以是使用自己定义的类,只要构造函数能够满足属性个数以及类型的要求就可以,
  这时候返回的就是自定义的类的对象。
-----------------------------------

参数设置问题(共有四种方法,详见课件,这里只讲其中两种):
我们可以这么写:
Query q = session.createQuery("from User where username=? and password=?");
q.setString(0,"aa");
q.setString(1,"aa");
q.uniqueResult();

或者这么写:
Query q = session.createQuery("from User where username=:name and password=:pw");
q.setString("name","aa");
q.setString("pw","aa");
q.uniqueResult();

或者:(注意这种情况是针对于javaBean所设置的)
也就是说password=:pw是针对javaBean设置时不用更改属性名而设置的别名机制,只要javaBean中
的属性名和冒号后面的别名相同的话就可以直接把javaBean中的属性对应值赋给等号前面的对应的实体类的
属性中去。

Query q = session.createQuery("from User where username=:name and password=:pw");

UserProxy u = new UserProxy(1,"aa","aa"); //这是在上面创建的类的实例!
q.setProperties(u); //也就是到u这个对象中把同名的属性name和pw取出来设置到上面的HQL字符串中
     //u这个对象所对应的类是我们在上面创建出来的,里面有两个属性一个是name,一个是pw。
User u1 = (User)q.uiqueResult(); //因为得到的是一条记录,所以用uniqueResult方法得到返回值(是个Object)
System.out.println(u1.getUsername());

--------------------------------------
order by 和 group by 子句的使用和sql是一样的。

今天上午主要掌握
1 让HQL执行的形式
2 如果选取一部分属性和全部属性的话,分别是怎么作

---------------------------------------
下面说说HQL的更新,删除和插入是如何实现的:

传统的session接口的save、update和delete方法实现时都只是针对一个
对象,无法实现批量的增删改查操作。

HQL直接更改数据库,不影响缓存,但是save、update和delete方法缓存和
数据库中的记录都更改

session.beginTransaction();

User u = (User)session.get(User.class,new Integer(1);
Query q = session.createQuery("update User set loginTimes=2 where id=1");
//注意这样是批量更新处理,如果没有where条件的话,会把表中记录全部更新
//要是直接利用session.update(u)的话,一次只能更新一条记录,不能批量处理
q.executeUpdate();

u.setLoginTimes(new Integer(5)); //注意这句话!这里改的是缓存中的u,问题是事务提交后,这个缓存中的变化是否
        //被提交给数据库呢?事情是这样的,假如加载进入缓存的时候u这个对象的登陆次数是5
        //后来我用批量更新语句将它在数据库中的记录改为了6,结果我在这里设置了一个5,因为
        //和以前的缓存相比没有变化,所以不会反映到数据库中去,数据库中仍然是6;
        //但是如果我在这里设置了一个7的话,由于和之前缓存中加载进来的5不同了,这就会反映
        //到数据库中去,结果事务提交后数据库中的记录结果就是7了!

System.out.println(u.getLoginTimes()); //用来观察缓存中的对象是否被更新
//这里有一点需要注意:如果上面是load加载的话,load语句执行的时候并没有读数据库,在更新完结后
//才去读取数据库,它是延迟加载的,所以结果会是2,也就是数据库记录更改后的结果;如果是get加载的话,
//由于没有延迟加载机制,它会直接去数据库中读取值,然后把值直接读入缓存中,所以这里打印出的结果
//将会是更改数据库记录前的结果,也就是缓存中的结果,但是同时数据库中的相应记录已经被更新了!
session.getTransaction().commit();
--------------------------

现在还落了QBC、QBE和主键生成器的内容,这将在周四上午补完整。

----------------------------
现在总结一下这20天田老师讲课的内容:
1 SQL语句:
DDL/DML/DCL/QL
DDL:create:table/view/sequence/syno/index
 drop:
 alter:
DML:update table set col=?
 insert into table(id,name……) values (1,"yuanbin",……)
 delete from table
 truncate table
 merge                注意:truncate和merge仅仅属于oracle数据库!!
DCL:grant role to user
 revoke role from user
QL:select
   from
   where
   group by …… having ……
   order by

2 Oracle的安装、管理、使用
(1)sqlplus/isqlplus的使用
(2)Oracle监听器、本地NET名的配置
(3)什么是SID,如果有两个库存在的话,如何修改SID

3 Oracle的SQL函数
(1)和数字相关的
(2)和字符相关的
(3)和日期相关的
(4)和null相关的:nvl,nullif
(5)connect by
(6)case when
 decode

4 JDBC
(1)驱动程序类型
(2)获取连接的方式DataSource和DriverManager
(3)JDBC的事务
(4)三种语句Statement,PreparedStatement,CallableStatement
(5)结果集的getter方法和update方法。
(6)结果集的属性有三种,哪三种,如何指明呢?(在创建语句的时候指明)
(7)离线结果集的原理是什么??
(8)数据库连接池的原理是什么?

5 Hibernate
(1)配置文件和映射文件-几种配置方案,如何加载映射文件和配置文件
(2)直接通过对象进行增删改查的方法,也即session的几种方法区别,
   包括save persist saveOrUpdate
   update load->setter saveOrUpdate
   update merge
(3)对象的三种状态(临时、脱管、持久),各有什么区别?
(4)熟练掌握HQL语句

6 基础知识讲解
(1)对象的equals方法和hashCode方法怎么重写的问题以及为什么要重写?在什么情况下应用?
(2)集合Collection->list/set
    Map
(3)JavaMail

重点:SQL语句,JDBC和基础知识三大块

-------------------------------------------
下午是张老师和我们一起进行对Hibernate的复习,主要思想是告诉我们配置信息可以用手工
编码的形式(也就是addProperties方法一条条的加入属性即可),在这种手工编码的形式配置
文件的时候,是不用xml文件或是属性properties文件的。


在执行了session.save(user)之后,user对象是否和原先的user对象一致呢?
这可不一定,要看是不是主键自动生成,如果是自动生成的话,之前如果没有主键的话,save之后
对象必然就有主键了。
也就是说save方法可以改变user这个对象的属性,这是没有问题的。

在save方法给user赋主键之前,是必须首先得到正确的主键值的,那么save方法是如何得到主键的呢?
通过select max(id)方法得到最大的主键,加1就行了

当然顺带一提的还有一点:statement的executeUpdate方法插入了一条记录之后,调用statement的
getGeneratedKeys方法可以得到自动生成的主键(参看JDK帮助),但是并不是每一家驱动程序厂商
都支持这一个方法!

#hibernate.jdbc.use_get_generated_keys false
注意上面那句话在hibernate的property文件中可以找到,把前面的井号去掉,然后把false改为true即可使用上面所说的
getGeneratedKeys方法了,这是jdbc3.0的特性,当然使用之前你最好保证你使用的jdbc驱动支持这个东东。

映射文件的例子可以在hibernate3.1的解压后的jar包中的eg(example)中找到。
同样的,配置文件的信息相应的也在那里可以找到。

Configuration不用configure()方法是否可以?
完全可以,只要hibernate.properties文件在工程目录下就可以了。完全不用properties文件的话也行,
可以使用手工的方法,用Configuration类的addProperties方法,一条属性一条属性的去添加属性就可以了。
当然没有人会去这么作因为太繁琐了……

比较常用的方法就是xml和properties属性文件,当然由于xml的良好可读性,实用中大多使用xml来进行配置。

Configuration的addClass、addResource、addFile是用来加入映射文件的,当然配置文件中的
mapping元素的resource属性也可以设置映射文件,这样就不用那三个add方法来加载映射文件了。

问题:完全不用Hiberante配置文件是否可以?
可以的,就像前面所说的,使用addProperties方法,你自己去一条一条的加载属性吧,就是麻烦了点。
--------------------------------------------------

张老师就说了这么多,可以看出来他今天的对细节的过分计较相对于前两天少的多了,大概是清楚这样对于
教学进度也有影响吧,又或者是,因为明天休息所以今天想放松一下?不管怎么样,又是一个礼拜的课程结束了,
感觉自己的日记中现在几乎全是培训的课程内容,有点不能叫做日记了,毕竟自己的东西太少了,好多随感随想什么
的也没什么兴致写了,人变的可真快,呵呵,难得今天下午有点空闲,再次把这周的情况说一说:

这一周主要是田老师讲解Hibernate,由于Hibernate的配置是第一次,所以一开始感觉有些繁琐,而且田老师
好像对于某些细节方面的东西抠的过于细致了,比如更新的先后位置以及……具体我现在也有点说不清楚,尽管
当时把我讲的很乱,但是值得欣慰的是,田老师讲的所有的东西都在我的日记中留下了相应的印记,倒是不怕会丢掉。
过了两三天后,情况稍微的好了那么一点,田老师的Hibernate课程感觉也好接受一些了,但是就在这个时候,突然
转成了张老师给我们讲JavaMail。

原来我没有想过这会给我们的课程带来什么变化,但是事实证明我错了,张老师第一天的讲解过于天马行空,说是
讲邮件,但是事实证明他完全跑题了,比如带着我们阅读jdk的javaMail文档时,他有的时候会禁不住想到一些
别的java语言的特性,然后情不自禁的给我们大讲特讲起来,有的时候还有些意犹未尽,这样浪费了不少的时间。
不但浪费了时间,他这种有的时候突然插到别处的讲课模式也给我们底下人的听课带来了影响,他讲javaMail的第一天
是我笔记记得最乱的一天,完全抓不住他的讲课重点,闹的我的笔记也是乱七八糟的。张老师似乎也意识到了这一点,
他在第二天收敛了许多,但是下午的时候还是犯了老毛病,一个用代理发送邮件的试验几乎整了一个下午,服了……
总之他讲课的这两天给我感觉是很混乱,眉毛胡子都在那里,而且还纠缠在一起,感觉很不爽,而且他讲课举的例子
太多太多,有的例子似乎没有必要举,但是也被举出来了,听起来就很别扭……

张老师讲课用的是javaMail的书稿,书稿是方老师写的,方老师以前也是张老师的培训学员,后来就在张老师那里当
助教了,说到这里我想起了一件事情,就是协议中所谓的底薪3000元的问题,当时怎么也想不明白,后来才在一次偶然
的机会里知道了这件对我们似乎200%有利的事情到底是怎么回事。

某培训机构这个培训班刚刚成立,课程的系统编排,教材的编写,人员的管理,以及招生的代理等诸多方面都有问题,反映
到具体的现实中来就是人手不足。所以张老师他们迫切希望能够有学员能够在毕业后留下来帮忙(主要是帮忙编写书稿)
,这样能够缓解他们的压力。田老师现在就经常在课上布置一些问题专门找人去整理然后叫那些整理好的人把文档提交给
他们,这样方便把这些东西做成书稿。如果学生毕业后找不到正式期工资大于3000的工作的话,那么按照协议来,应该是
要向某培训机构报道的,怎么个报道法呢?自然要来向他们告知你目前的情况的,某培训机构希望学员能够留下来整理书稿,
而且他们给学员预备的这个工作薪酬正好可以大于3000,这下子就能够解释协议中的条款了,学生只要答应帮助整理书稿
肯定能够有底薪3000的工作,这可以说是某培训机构的一道底牌吧,呵呵,只不过之前不会说出来罢了。当然并不是说这里
学出来的学员找3000元的工作很困难,而是考虑到特殊情况,比如有的人学历很差,基础也很差的话,可能4个月之后不会
有太明显的进展,这样的人可以选择留在某培训机构,也没有和协议上的条款相矛盾。

当然上面全部是我的个人意见,还有待时间的证明,这个月的20日就是一期学员的企业见面会,到时候一切都自然见分晓了,
我们拭目以待吧……

还是比较喜欢田老师讲课的风格,虽然不温不火,不急不慢,平平常常,语气倏缓,但是课程重点突出,总结及时,听起来
笔记也记得顺利,真是十分的不错,尤其是在听了张老师的两天课程后更是让我感受到了“什么东西都是失去了才感受到可贵”
这句话的真谛。当然也并不是说张老师讲课就不行,他讲课抠的很细致,有些细节是很值得讨论的,但是问题是,有些本不该
讨论的东西也被花了很大的时间讨论,而这些花大时间讨论的东西反而搞乱了我们的思路。而且有些问题本来是不必要举很多
例子来讲明白的,但是张老师花了很多时间去讨论它,这好像有点舍近求远了……还有一些不必要的试验之类的东西,不能因为
这个而影响正常的上课进度啊,这些意见有的时候必须得当面提清楚。

张老师和田老师都是对学生很负责任的老师,那天聚餐后对田老师提出的几个意见他全部接受了,并在第二天就反映到了课程中,
很不错。张老师其实也是个很喜欢和学生交流的人,就是有的时候过于沉迷细节有些把持不住自己,结果导致有时候延误了课堂
进度,出发点都是好的,负责任的老师就是可信赖的,虽然我上面对张老师的评价贬大于褒,但是不能仅仅以此就否定一个人,
我们作为学生没有能够及时在课上指出老师的错误并提出相应的意见也是不对的,可以说我们也是有责任的,过不了多久,田老师
的脚本、数据库设计和P/SQL语言就会讲完,大概下周的第5、6天左右就会是张老师的javaWeb了,到时候如果觉得不对的地方
我一定要及时的提出来,这样是对自己负责,可能也是对班里的其他人负责吧,呵呵,话有点说大了,上课的时候多和老师交流
,0距离的表述自己的意见和看法,本来就是正当的嘛,无可厚非,哎……废话说多了,就此打住吧。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值