3.2HibernateSession操作的三种状态(背)

Session操作过程中的pojo对象存在三种状态:

1) 瞬时态:该对象在数据库中没有对应的数据

2) 持久态:数据库中存在该对象对应的数据,同时操作该对象的Session也存在。

3) 游离态:数据库中包含该对象对应的数据,但操作此对象的Session已经不存在或被关闭了。

三种状态之间的转换:

瞬时 à 持久:save()saveOrUpdate()

持久 à 瞬时:delete()

持久 à 游离:close()

游离 à 持久:update()saveOrUpdate()

针对持久态对象,Hibernate还存在以下两个特点:

1) 持久态对象,在同一Session中只存在同一个。

a) 如果连接不关闭,多次查询同一条数据,只返回同一个对象,也就是只查询一次数据库。

b) 此功能也被称为一级缓存,但实际开发中实用性很低。

2) 修改持久态对象的属性,可以自动同步到数据库对应的数据中。

a) 当修改了一个持久态对象的属性,而且提交了事务,则数据库自动调用更新操作,也一起修改。

b) 当登陆后,要求将当前系统时间,作为最后登陆时间保存到数据库中时,可以使用。

3.3Struts2 + Hibernate实现用户登陆功能(重点)

先建立项目,根据需要加入框架支持。

加入Hibernate:略

加入Struts2

支持加入后,先建立一张用户表。

CREATE TABLE T_User (       userid         varchar2(40)        primary key ,       real_name      varchar2(20)        not null,       password       varchar2(32)        not null,       regist_date    date                default sysdate,       last_login_date         date                          );INSERT INTO t_USER (userid,real_name,password)VALUES ('zhangsan','èy','123');commit;

根据表,生成映射。

主键使用assigned方式生成

生成映射后,根据需要,完成DAO的方法

public class TUserDAOImpl implements ITUserDAO {    public boolean isLogin(TUser user) throws Exception {        String hql = "FROM TUser AS u WHERE u.userid = ? AND u.password = ?";        Query query = HibernateSessionFactory.getSession().createQuery(hql);        query.setString(0, user.getUserid());        query.setString(1, user.getPassword());        List
allUser = query.list(); if (allUser != null && allUser.size() > 0) { // 登陆成功 // 取得查询的结果 TUser result = (TUser) allUser.get(0); // 根据引用传递,将值设置到传入的user中 user.setRealName(result.getRealName()); user.setRegistDate(result.getRegistDate()); user.setLastLoginDate(result.getLastLoginDate()); return true; } return false; }}

再实现Service以及工厂的代码。

后台代码实现后,开始编写前台Struts操作代码。

导入Struts2标签库,完成表单

<%@ taglib uri="/struts-tags" prefix="s"%>

表单可以使用普通标签,也可以使用Struts2标签

用户名:
密码:

用户名:
密码:

编写Action类,完成验证的操作。

public class TUserAction extends ActionSupport {    private TUser tuser;    public TUser getTuser() {        return tuser;    }    public void setTuser(TUser tuser) {        this.tuser = tuser;    }    public String login() throws Exception {        boolean flag = ServiceFactory.getITUserServiceInstance().login(tuser);        // 根据结果,决定跳转的位置        if (flag) {            // 将用户保存到session属性范围中            ServletActionContext.getRequest().getSession().setAttribute("user",                    tuser);            return "suc";        }        // 添加错误信息,页面使用标签显示        super.addActionError("用户名或密码错误,请重新输入!");        return "input";    }}

配置这个Action,在struts.xml中完成。

/pages/suc.jsp
/index.jsp

完成suc.jsp中显示用户信息的功能

用户登陆成功,当前登陆用户为: ${user.userid}

index.jsp中提示错误信息

                

测试项目,会提示以下错误信息。

java.lang.NoSuchMethodError: antlr.collections.AST.getLine()I

java.lang.NoSuchMethodError: antlr.collections.AST.getLine()I

这种错误是由于项目中加入了多个版本的支持jar包,各个版本之间有相同的类,但方法不同,造成冲突。

这里的冲突jar包是Struts2加入的2.7.2.jar造成的,需要将该包删除,该包是MyEclipse工具提供的,因此需要通过MyEclip-se的操作来删除,无法直接删除。

删除后,必须重新发布项目,并重新启动服务器才可以。

注意这里的包冲突问题。

3.4Hibernate中的复合主键映射(了解)

实际开发中,只有当出现多对多关系时,才有可能出现复合主键的表,例如:学生选课功能,需要设计,学生表,课程表和选课表,其中选课表应该只有两个字段(学生id,课程id),而且应该是复合主键。

但实际开发中,Hibernate推出了多对多关系映射的功能,该功能专门针对多对多关系中间表进行处理,因此复合主键映射在开发中没用了。

这里建立一个中间表,来简单看一下复合主键映射的实现方式,要求了解HQL中类关系查询的形式

先建立一张选课表

CREATE TABLE course (       cid           number(8)          primary key ,       title         varchar2(50)       not null                  );INSERT INTO course VALUES (1,'Javaù±ó·¨');INSERT INTO course VALUES (2,'JavaWeba·¢');INSERT INTO course VALUES (3,'Javaóòμòü');INSERT INTO course VALUES (4,'Androidó|óa·¢');INSERT INTO t_user (userid,real_name,password) VALUES ('lisi','à','abc');commit;
create table user_course (       userid             varchar2(40)      ,       courseid           number(8) ,       primary key (userid,courseid));INSERT INTO user_course VALUES ('zhangsan',2);INSERT INTO user_course VALUES ('zhangsan',4);INSERT INTO user_course VALUES ('lisi',1);INSERT INTO user_course VALUES ('lisi',3);commit;

准备生成映射

主键生成方式可以不选,因为Hibernate认为,只要是复合主键,不可能是自增长的。

生成后会发现,多出了一个Id类,该类出现的原因是因为主键的作用。

主键的作用是唯一标识,保证数据不重复,普通的单字段主键,在映射时,都是映射成普通的数据类型。

但复合主键要比较重复,必须比较多个键都相同,才能算重复。

因此,Hibernate自动生成了id类,并在里面包含了useridcourseid,同时通过覆写equalshashCode方法,来完成是否重复的比较,这样就可以自动针对id判断是否重复了。

映射文件中也体现了这个关系。

编写一个操作,来看类之间关系的查询。

实现根据某个学生id查询该学生选择的课程信息。

public class Test {    public static void main(String[] args) {        // UserCourse uc = new UserCourse(new UserCourseId("zhangsan", 1));        // UserCourse uc2 = new UserCourse(new UserCourseId("zhangsan", 1));        //             // System.out.println(uc.getId().equals(uc2.getId()));        String hql = "FROM UserCourse AS uc WHERE uc.id.userid = ?";        Query query = HibernateSessionFactory.getSession().createQuery(hql);        query.setString(0, "zhangsan");        System.out.println(query.list());    }}

这里一定要注意,按照类的关系,查找数据,通过UserCourse找到里面的id,再找到里面的userid,作为条件,不要管数据库里表是怎样的设计和关系。

4、总结

1、Struts2 + Hibernate完成登陆

2、背:三种查询,getload的区别,Session的三种状态以及转换,持久态对象的特性。

3、掌握类之间关系的HQL编写方法