1月29日——培训第58天

来源:互联网 发布:itunes软件官方下载 编辑:程序博客网 时间:2024/05/22 15:41

Struts和hibernate的一个综合应用的小例子:
selectCourse:

使用MyEclipse加入Struts1.2特性,手工加入hibernate所需要的jar文件和
mysql驱动。

配置可以使用hibernate属性文件,只需要把该注释的给注释掉就可以了,记得把url后面加上
useUnicode=true和characterEncoding=gbk

别忘了加上下面这句:
hibernate.current_session_context_class thread

应用程序一加载就应该把sessionFactory实例化出来,保证sessionFactory实例只有一个。

//常量类:
package cn.itcast.util
public class HibernateUtil
{
 public static final String HIBERNATE_SESSION_FACTORY =
          "cn.itcast.hibernate.session_factory" ;
 public static SessionFactory getSessionFactory(HttpServletRequest request)
 {
  SessionFactory factory = null ;
  factory = (SessionFactory)request.getSession().getServletContext()
        .getAttribute(HibernateUtil.HIBERNATE_SESSION_FACTORY);
  return factory ;
  
 }

 public static Session getHibernateSession(HttpServletRequest request)
 {
  return getSessionFactory(request).getCurrentSession() ;
 }
}

需要一个监听器:(如果不用监听器的话,可以使用Struts中的plug-in插件机制,里面的init方法可以
用来加载sessionFactory)

package cn.itcast.listener

public class ApplicationListener implements ServletContextListener
{
 public void contextDestroyed(ServletContextEvent arg0)
 {
  ServletContext application = event.getServletContext() ;
  SessionFactory factory = (SessionFactory)application
         .getAttribute(HibernateUtil.HIBERNATE_SESSION_FACTORY);
  factory.close() ;
 }

 public void contextInitialized(ServletContextEvent arg0)
 {
  SessionFactory factory = new Configuration().configure()
             .buildSessionFactory();
  //映射文件需要xml文件去指定,所以这里就不需要addClass来指定了……
  //可以把前面的那个hibernate.cfg.xml中的其他配置都去掉,只留下:
  //<hibernate-configuration>
  //<session-factory>
  // <mapping resource="" />
  //</session-factory>
  //</hibernate-configuration>
  ServletContext application = event.getServletContext() ;
  application.setAttribute(HibernateUtil.HIBERNATE_SESSION_FACTORY,factory) ;
 }
}

监听器肯定需要在web.xml中注册:
<listener>
 <listener-class>cn.itcast.listener.ApplicationListener</listener-class>
</listener>


建立数据库表:
courses表:
id           integer类型 
coursename  varchar(100)类型
period Integer类型

students表:
id           integer
name         varchar
scores       integer
tea_id       integer
password     varchar
loginTimes   integer       默认值为1
loginTime    Timestamp 

学生和课程之间是多对多的关系,二者之间必然要有一个关系表
course_student:
course_id       Integer
student_id      Integer
以上两个字段都不设为主键

----------------------------------
新建实体类vo包:

public class Student
{
 private int id ;
 private String name ;
 private String password ;
 private int scores ;
 private int loginTimes ;
 private Timestamp loginTime ;
 private Set courses = new HashSet();
 //加入getter和setter方法
}

和这个类一起要有个映射文件:
<hibernate-mapping package="cn.itcast.vo">
<class name="Student" table="students" auto-import="true">
 <id name="id">
  <generator class="identity" />
 </id>

 <property name="name" />
 <property name="scores" />
 <property name="password" />
 <property name="loginTime" />
 <property name="loginTimes" />
</class>

//在配置文件中加上:
<mapping resource="cn/itcast/vo/Student.hbm.xml" />
--------------------------------------------------
学生登录,LoginAction中验证用户名和密码是否正确,使用Hibernate的HQL,如果查到的
话会返回一个实体,然后可以将其存入session。


现在学生表里面新加一个用户jsp,密码也是jsp

然后建立一个登录的页面,引入htmlform:
<body>
 <html:form action="/login">
 user: <html:text property="username" /> <br>
 password: <html:password property="password" /><br>
 <html:submit />
 </html:form>
</body>

在Struts的配置文件中:
<form-beans>
 <form-bean name="loginForm" type="cn.itcast.struts.form.LoginForm">
  
 </form-bean>
</form-beans>

然后还需要与之对应的Action文件,并使用自动生成的功能生成配置和Action。

public ActionForward execute()
{
 String target="failure" ;
 LoginForm loginForm = (LoginForm) form ;
try
{
 SessionFactory factory = HibernateUtil.getSessionFactory(request) ;
 Session session = null ;
 session = factory.getCurrentSession() ;
 session.beginTransaction() ;
 Query query = session.createQuery
  ("from Student where name=:username and password=:password") ;
 query.setProperties(form) ; //将form中同名参数设置进去!
 //当然也可以是query.setProperties(loginForm);
//底下这种写法也可以,但是不提倡,太麻烦了
/*
 Query query = session.createQuery("from Student where name=? and password=?") ;
 query.setString(0,loginForm.getUsername());
 query.setString(1,loginForm.getPassword());
*/
 Student stu = (Student)query.uniqueResult() ;
 if(stu!=null)
 {
  target = "success" ;
  stu.setLoginTime(new Timestamp(System.currentTimeMillis()));
  stu.setLoinTimes(stu.getLoginTimes() +1)
  request.getSession().setAttribute("user",stu);
 }
 session.getTransaction().commit() ;

 catch()
 {
  if(session!=null&&session.getTransaction()!=null)
  {
   session.getTransaction().rollback() ;
  }
  e.printStackTrace() ;
 }
 finally
 {
  if(session!=null)
  {
   session.close() ;
   session=null ;
  }
 }

 return mapping.findForward(target) ;
}

----------------------------------------------

你好,${user.name},这是你第${user.loginTimes}次访问!

---------------------------------------------------------------

下午课程开始:
登陆后的欢迎页面welcome.jsp上除了显示上面的访问问候语外,还要列出选的课程内容

welcome.jsp

<body>
 <a href="${pageContext.request.contextPath}/modify.jsp">修改个人信息?</a>
 <a href="${pageContext.request.contextPath}/selectCourseInput.do">选课?</a>
</body>


modify.jsp:
<body>
 <html:form action="/modify">
  <html:text property="username" value="${user.name}" /><br>
  <html:text property="password" value="${user.password}" />
 </html:form>
</body>


注意vo里面得再建一个实体:
package cn.itcast.vo;
public class Course
{
 private int id ;
 private String coursename ;
 private int period ;

 //重新实现equals方法在这里显得尤为必要,因为只要id一样课程就一样
 //而且有了equals,就必须有hashCode

 public boolean equals(Object obj)
 {
  if(obj==null)
  {
   return false ;
  }
  //看传入的对象是不是Course的
  if(obj instanceof Course)
  {
   Course c = (Course)obj ;
   if(c.getId()==this.id)
   {
    return true ;
   }
  }
  return false ;
 }

 public int hashCode()
 {
  return id ;
 }
}

//学生那里持有课程的集合
<hibernate-mapping package="cn.itcast.vo" auto-import="true">
<class name="Student" table="students" >
 <id name="id">
  <generator class="identity" />
 </id>

 <property name="name" />
 <property name="scores" />
 <property name="password" />
 <property name="loginTime" />
 <property name="loginTimes" />
 
 <set name="courses" table="course_student">
  <key column="student_id" />
  <many-to-many class="Course" column="course_id" />
 </set>
</class>


<class name="Course" table="courses" >
 <id name="id">
  <generator class="identity" />
 </id>

 <property name="coursename" />
 <property name="period" />
 
</class>

新建一个Action:接收那个selectCourseInput.do的地址!
如果成功的话转向listSelectCourse.jsp:

public class SelectCourseInputAction extends Action
{
 //学生选了哪些课?已经开的课程有哪些课??都要列出来
 //也就是列出所有的课程,左边有个多选框,学生选的课程要打上钩儿。
 public ActionForward execute()
 {
  SessionFactory factory = HibernateUtil.getSessionFactory(request);
  Session htSession = null ;
  Student stu = (Student)request.getSession().getAttribute("user");
  //上面这个stu处于托管状态
  if(stu==null)
  {
   return mapping.findForward("failure") ; 
  }
  //stu.getCourses().iterator();这么写是不行的,处于托管状态session关闭的时候无法
  //关联!现在的问题是如何让student再次和session关联……可以考虑使用update,但是一旦
  //执行了update就必然执行一条语句……
  try
  {
   htSession = factory.getCurrentSession() ;
   htSession.beginTransaction();
   htSession.lock(stu,LockMode.NONE) ;//这就把session和stu关联起来了。
   //现在要把集合加载进来,但是问题是延迟加载,所以你可能想这么写:
   //stu.getCourses().iterator();但是这种写法太别扭了,而且根本没有东西去操纵这个
   //迭代器, 学生登录进来他选的课程并没有被加载进来,我们想加载进来,所以就要让student
   //和session再关联,lock就是把stu和session关联
   //其实htSession.update(stu)也可以让stu和session再次关联,但是要至少执行一条语句。
   
   Hibernate.initialize(stu);//只初始化stu中的非集合属性!这句话在这里写没意义!

   Hibernate.initialize(stu.getCourses());//初始化stu中的集合,找出登录的学生所选的课程。
   //courses是延迟加载的,因为属于关系,所以如果不initialize的话,关系就不能被初始化,
   //stu.getCourses()也就是空的……必须先lock令session和对象先关联(让已经处于脱管状态的实体
   //再次与session关联起来,但是不进行数据库的操作),然后初始化关系,将在登录没有加载进来的courses
   //集合加载进来,initialize是要进行数据库操作的,不然关系没有办法加载关系


   Query query = htSession.createQuery("from Course");
   List list = query.list() ;

   htSession.getTransaction().commit() ;
   request.setAttribute("allCourses",list) ;//将所有的课程都存起来。
  }
  catch(HibernateException e)
  {
   if(htSession!=null&&htSession.getTransaction()!=null)
   {
    htSession.getTransaction().rollback();
   }
   e.printStackTrace() ;
  }
  finally
  {
   if(htSession!=null)
   {
    htSession.close();
    htSession = null ;
   }
  }
  return mapping.findForward("success");
 }
}


在listSelectCourse.jsp中:
要列出所有的课程并且把所有该学生选了的课程要打上钩

<body>
 <form action="" method="post">
 <%Set l = ((cn.itcast.vo.Student)session.getAttribute("user")).getCourses();%>
  <logic:iterate id="course" name="allCourses">
  <%
   String str = "" ;
   if(l.contains(pageContext.getAttribute("course")))
    str = "checked" ;
  %>

  //allCourses是上面请求作用域中的属性名
   <input type="checkbox" name="course" value="${course.id}" <%=str%>/>${course.coursename}
   <br>
  </logic:iterate>
  <input type="submit" />
 </form>
</body>

 


上面的那部分页面代码可以替换成为下面的:
<body>
 <form action="" method="post">
 
  <logic:iterate id="course" name="allCourses">
  <c:set var="checked" value="" />
  <c:if test="${my:contains(user.courses,course)}">
  //这个my:contains(user.courses,course)是我们自定义的表达式函数,要求是公共且静态的
  //并且要在tld中去配置!
   <c:set var="checked" value="checked" />
  </c:if>

  //allCourses是上面请求作用域中的属性名
   <input type="checkbox" name="course" value="${course.id}" ${checked}/>${course.coursename}
   <br>
  </logic:iterate>
  <input type="submit" />
 </form>
</body>

package cn.itcast.taglib ;

public class ELFunction
{
 public static Boolean contains(Collection collection,Object obj)
 {
  if(collection == null || obj==null)
  {
   return new Boolean(false);
  }
  return new Boolean(collection.contains(obj)) ;
 }
}
//之所以要使用Boolean,是由于下面在tld中要注册这个类,使用boolean的话就没法注册了,
//当然也可以尝试其他方法,比如你让它返回一个特定的字符串,在页面中条件标签里面比较一下就可以了。
my.tld中的配置

<tlib-version>1.1</>
<short-name>my

<function>
 <name>contains</name>
 <function-class>cn.itcast.taglib.ELFunction</function-class>
 <function-signature>
  java.lang.Boolean contains(java.util.Collection, java.lang.Object)
 </function-signature>
</function>

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

前天烧了一天,非常的痛苦,昨天虽然不怎么烧了,但是还是很没精神,今天是彻底好了,好的好像什么都没有发生
过一样,一般来讲,发烧后怎么也得象征性的来点流鼻涕或是咳嗽这样的感冒小症状吧,但是这次却什么都没有,简直
是“来也匆匆、去也匆匆”,还没明白怎么回事,一切就结束了……发烧和感冒有的时候确实一点关系没有,它是身体的
自我防卫机制,有可能是外部病原体的入侵,也有可能是身体内部出现了一些肉眼不可见的创伤什么的……谁知道呢,
挺想把这些事情搞清楚的,从一个完全客观的角度去想人这个物理的整体你就会发现很多事情都是搞不明白的,正因为
搞不明白,所以像什么“耶稣”、“真主”之类的货色还在世间苟延残喘,看着就让人痛心疾首,在科学技术是第一生产力的
今天竟然还有人信这种东西,而且还信的一塌糊涂,而且还有很多西方科学家也信这个!甚至如果你不信基督上帝的话连
当选美国总统都是白日做梦……还有比这更荒唐的事情么!生活在这个世界上固然是一种幸福,但是如果不能够看清事情的
真相那本身就是一种可悲!这些牛鬼蛇神什么的是否存在不重要,重要的是如果存在的话必须得拿出证据来证明它存在,
否则任何一个头脑清醒有逻辑的人都不会相信吧……

好像有点扯远了,既然已经扯到这里了,那就干脆再扯几句,以前接触过一个基督徒,是德国人,基督徒都很善良,这是
事实,如果每个人都像他们那样的虔诚的话,我们的世界将会比现在美好许多许多,中国之所以个人主义盛行,群体道德
缺失,社会责任感意识淡漠,其中的一个原因是因为我们国家是一个无神论盛行的国家,即便是城市里面的人也顶多是迷信个
星座什么的没别的了,当然还有其他原因比如初级阶段、贫富差距等等……又扯远了,再说这个德国人,他的身上体现出了
一个基督徒的善良无邪和一个西方人的高素质,佩服归佩服,但是他说的一句话实在是让我恶心的想吐:“科学是上帝所
创造的,所以人类没有办法用科学的方法去证明上帝的存在,你怎么能奢望用物来证明造物主呢?”

有的时候人和人真是没有办法互相理解,话能说到这个份儿上,逻辑能混乱到这个地步,作为一个来京的优秀德国工程师,也
真是难为他了,但又能怪谁呢?从小他父母就带他往教堂跑,背圣经、唱圣歌什么的,天天的那么耳濡目染,再加上那时候
正是一个人大脑的成型期,在那个时候雕琢入脑海中的固有观念确实能够影响人的一生……宗教这种东西,甭管它对人类社会
的发展是否有裨益(当然肯定是大有裨益,要不怎么哪一个国家领导都得大力的鼓吹保护宗教信仰呢?他敢不保护么?不
保护人家就造反了,你国家还怎么发展呢??),宗教骨子里就是人类的自我欺骗,我的一个同学就是,像每一个传统的
中国人一样,他曾想过高考金榜提名,但是不自信,于是呢,去拜观音,拜还不够,脖子上还挂个观音的饰物,显得很虔诚
的样子,最后梦想成真,还说什么心诚则灵,哎……纯属自欺欺人,不敢相信自己就寄希望于那些神灵,其实还是变相的相信
自己,我们人类有的时候就这么奇怪,即便你有的时候能把这些事情想的很清楚,但是时不时的也会犯一些和他们相同的错误,
就好比我前天发烧最严重的时候,模模糊糊的竟然也开始犯起迷信来了,简直是奇耻大辱,任何一个坚信科学唯物主义的人
都要坚决和这些谎言和欺骗划清界限,在信仰上犯错误是绝对不可以原谅的……

上边说了一大堆的昏话,酒疯也撒的差不多了,其实宗教本身没有什么不好,比起我们国家的一些该死的中医骗子和搞封建迷信
的那帮人渣比起来,人家宗教高尚多了,信奉基督的西方人的素质我们有目共睹,但是好归好,虚假的东西毕竟是虚假的,
如果我们人类不得不依靠一个虚假的信仰来通过自我欺骗的方式从而压制自己本能的邪恶来达到美化世界美化生存环境的目的,
这固然没什么不可以,但是总让人觉得……很悲哀,人类应该追求真实,在真实中获取内心的平静与安宁,而不是从谎言中聊以慰藉……