STRUTS+Hibernatre+Spring 组学习资料整理

一.学习目标

系统的研究Struts框架,HibernateSpring的运行原理以及分别DEMO演示Struts+HibernateStruts+SpringStruts+Hibernate+Spring的互相结合时的运行流程及相关具体配置。

 

二.详细资料

1.  STRUTS

validator验证学习笔记.doc

 

 

 

2.  Hibernate

1)什么是Hibernate

Hibernate就是帮助我们从面向对象的程序到关系型数据的映射,他可以帮助我们脱离具体的数据库细节,并可以帮助我们生成Sql语句,简化JDBC编程,这样就可以实现程序的面向对象化和数据库的移植。

 

              2HibernateJDBC相比的优缺点

                      AJDBC在对对象操作时要写大量烦琐的代码

例:PreparedStatement pt=con.prepareStatement(insert into “表名” values(?,?,?,?,?,?))

     Pt.setString(1,EntityBean.getXX());   

Pt.setString(2,EntityBean.getXX());

Pt.setString(3,EntityBean.getXX());……

               如果实体BEAN中有上百个属性,使用JDBC那将是会非常大工作量;

                        Hibernate可以直接对对象进行操作(saveObject)),省却了很多工作。

                    

BJDBC在处理多表连接时非常麻烦,如果要删除某条信息,需要知道关于此表的外联信息,即哪几张表和此表有外联关系,并需要同时删除所有外联表中的此信息,需要花费很多精力。

     Hibernate则可以在配置(cscade)自动建立这种多表关系,在对某表中信息操作会自动对其级联表的相关信息进行操作。

 

CJDBC在开发中要求程序员对底层的数据库结构(哪个表中有什么字段等)非常了解,才能够很好的使用SQL语句对数据库进行操作。

     Hibernate则使数据层完全被隐藏,程序员只需对映射的BEAN对象进行一些GETSET方法就可以对数据库进行操作,无须了解数据库的情况。

 

DJDBC在进行大批量操作时,如批量更新,删除n条记录时,正常情况下需要向数据库发送n次语句,性能很差。

     Hibernate可以使用batch功能可以将语句缓冲,最后一次发送给数据库,但性能提高不多。

而调用JDBCAPI进行操作能使时间缩短十几倍,所以在进行大批量操

作时最好的方法是调用JDBCAPI实现。

      

 

                (3)Hibernate配置相关的类

                     AConfiguration类(负责管理Hibernate的配置信息)

                             Configuration类是Hibernate的入口,新建Configuration实例时,configure()方法会自动寻找Hibernate.cfg.xml配置文件,如找不到会报错;如找到会读取SessionFactoryname属性,以后在建立SessionFactory时就会使用指定的映射文档。Configuration是仅在配置期使用的对象,从第一个SessionFactory开始建立的时候,它就失效了。

                         

           B  SessionFactory

负责Session实例的创建,SessionFactory是线程安全的,可以被多线程调用取得Session,但构造SessionFactory很费资源,所以一个应用中只初始化一个SessionFactory

          

           C.  Session

                             SessionHibernate的中心,Session不是线程安全的,所以如果多个线程共享一个Session就会产生混乱。所以会使用ThreadLocal类来建立一个Session管理的辅助类,可以有效隔离执行所需要的数据。

                             每一个请求应该使用一个单独的Session

                             每一个Session实例都可以看作为一个容器作为Hibernate的一及缓存。其作用一是减少程序访问数据库的次数,很多对象数据不是经常改变的,第一次访问时Hibernate将它放入缓存中,以后只要这个对象没有改动过,访问这个对象时,会先在Session的缓存内查找,如果有此对象,则直接返回应用程序;如果没有则发送 SQL语句到数据库,将字段组装成对象存于Session中。二是如果一个事务对数据进行了改变,这种变化不会立即传到数据库,Hibernate能对一些数据改变进行结合,从而对数据库进行最小数量的请求。

 

         4)对象在Hibernate中的状态

                            3种状态:

                                   A.瞬时状态

new命令开辟内存空间的对象(A  a  = new  A(“TOM”)),不和Session实例相关联,在数据库中没有和瞬时对象关联的数据,可以通过save()方法将瞬时对象插入到数据库中变成持久对象。   

                                B  持久化状态

                                          持久的实例在数据库中有对应的记录,并拥有一个持久化标志。

如果使用delete()方法,它就会变为瞬时对象。

持久对象总是与SessionTransaction想关联,在一个Session中,对持久对象的改变不会马上对数据库变更,必须在Transaction终止即执行commit()后才进行变更。

 

C.脱管状态

当一个Session执行close()后,持久对象会变为脱管对象。它与瞬时对象本质上是相同的,只是比瞬时对象多了数据标志的id

当脱管对象重新关联到新的Session上时候(通过update()等方法),会再次转变为持久的(脱管状态其间的改动将被持久化到数据库)。

 

               

5Session的常用方法

       ASessionsave()方法(保存)

              例子:Team t=new Team();

                       t.setId(“ 1000” );

                       t.setName(“TON”);

                       Transaction tx = session.beginTransaction(); // 开启事务

                       session.save(t);

                    tx.commit();

                    Session保存对象时先根据配置文件为主键id设置的生成算法.t指定一个id,然后见t对象放入Session缓存,事务提交时将新对象通过insert语句持久化到数据库。

                                   注意t.setId(“ 1000” );

这句话设置的id无效,会被配置文件为主键id设置的生成算法替代。如要强行指定id,则可以调用

session.save(t,“1000)

不过代理主键时候最好不要使用,以免主键的内容混乱;

 

Team t=new Team();

这句话说明save()方法只能对临时对象使用,而不能对脱管方法使用。

 

                  BSessionupdate()方法(更新)

                                    update()方法的特点是执行此方法时不发送SQL语句, Hibernate总是执行update()方法的。

                                   例:Team t=Teamsession.getTeam.class,“--id--“);

                                          t.setName(“TOM“);

                                          Transaction tx = session.beginTransaction(); // 开启事务

                                         session.updatet);

                        tx.commit();

上面代码中session.updatet);是没有必要的,即使没有调用在事务提交时数据变更仍然会提交到数据库中,其实大部分情况下update()只是为了关联一个脱管对象到持久状态。

另外如果将session.updatet);更换成session.save(t);那么在清理缓存时Hibernate仍然会发送一条update语句以保证脱管对象和数据库记录一致。

注意:Team t=Teamsession.getTeam.class,“--id--“); 

         说明update()方法只能对脱管对象进行操作而不能对临时对象进行操作。

 

                 CSessionsaveOrUpdate()方法

实际应用中往往不会注意对象的状态是临时还是脱管,所以为了防止save()和update()方法的错误应用,就产生了此方法,它会自动判断对象的状态来选择合适的方法来操作。

 

                 DSessiondelete()方法

                                   此方法负责删除一个对象(包括持久对象和脱管对象)

                                   例:Team t=Teamsession.getTeam.class,“--id--“);

                                          Transaction tx = session.beginTransaction(); // 开启事务

                                         session.deletet);

                        tx.commit();

                                   在调用此方法进行删除时,会有一些性能问题,特别是在大批量删除时,如果有10000条记录则Hibernate会向数据库发送10000delete语句。

                                          所以在大批量删除时需要使用bulk delete操作:

                                          Query q=session.createQuery(“delete from 表”)

                                          q.executeUpdate();

                                   但仍然会有问题,删除后的数据会在缓存中存在,查询时可能得到数据库不存在的数据。

                                  

E. Get()方法

例:

…….// 打开session,开启事务

Stu=(Student)session.get(Student.class,”ID”);

……//提交事务,关闭Session

                             Get()方法的执行顺序如下:

                              首先通过IDSession缓存中查找对象,如果存在此ID主键值的对象,                                                                                  直接将其返回。

                              在二级缓存中查找,找到后将其返回。

                             如果在Session缓存和二级缓存中没找到,则数据库中加载拥有此ID                                                                      对象。

                            也就是说,get()方法并不总是导致发送SQL语句,只有缓存中无此数据                       时,才向数据库取得数据。

 

                 F. load()方法

                               Load()方法和get()方法都能通过主键ID值从数据库中加载一个实体对                         象。

 

 

                                   (1)get()方法

                                          例:….//打开Session,开启事务

                                                 Student stu=(Student)session.get(Student.class,”noExitld”);

                                                 …..//提交事务,关闭Session

                                                 If(stu=null)

                                                        System.out.println(“stu对象为null”);

                                   (2)load()方法

                                          例:….//打开Session,开启事务

                                                 Student stu=(Student)session.load(Student.class,”noExitld”);

                                                 …..//提交事务,关闭Session

If(stu=null)

   System.out.println(“stu对象为null”);

可以看到当对象不存在并且是立即加载时,get()方法返回                          null,load()方法弹出了例外。因此使用load()方法时,要                            确认查询的主键ID一定是存在的。

 

 

G. Query接口

1Query query=session.createQuery(“from s where s.age>? and s.name = ?”);

2Query query=session.createQuery(“from s where s.age>age and s.name = name”);

 

HQL传递参数时有多种方式,最常用方式如上,然后需在后面对上方所传直进行设定

1)时

                     query.setInteger(0,25);

                     query.setString(1,”tom”);

              2)时

                     query.setInteger(age,25);

                     query.setString(name,”tom”);

    也可将Bean传入参数,query.setEntity(“age”,Student

 

       H. List()方法

                    Query query=session.createQuery(“from s where s.age>?”);

                                   query.setInteger(0,25);

                                   List list=query.list();

                                   Forint i=0i<list.size();i++

                                          Team t=(Team)list.get(i);

                            如上就获得了一组数据

 

                       I. uniqueResault()方法

                            uniqueResault()方法必须是查询返回的集合中只有一个对象时才可引用

                            :

                                   Query query=session.createQuery(“from s where s.age= 25 );

                                   Team t=(Team)qyery. uniqueResault();

                                   这时候不必须确定表中age=25的记录只有一条,否则将抛出错误.

 

                  6Hibernate的事务管理

                                   Hibernate的事务默认情况下采用JDBC事务管理,JDBC事务这里不                       做具体阐述。

                                当多事务并发时,为避免产生并发时产生的数据访问错误需要对数据                            进行锁定,有2种方法。

 

            A。悲观锁定

              悲观锁定一如其名称所示,悲观的认定每次存取资料时,其他的客户                            端也会存取同一笔数据,因此对该笔数据进行锁定,直到自己操作完                                成后解除锁定,它是一种阻止并发事务访问同一数据的一种机制。

              一些数据库,比如ORACLE,提供了一个SQL语句:select….for                                  update,以此来明确地指定数据库使用悲观锁定。可以在Hibernate                                的配置文件中检查当前所用的数据库是否支持for update特性,如果不支                      持,则Hibernate执行普通的、没有for update在句子最后的select语句。

              如果要在事务中使用悲观锁,则可以像下面这样写:

       Transaction tx=session.beginTransaction();

       //取得持久化USER对象,并使用LockMode.UPGRADE模式锁定对象

       User user=(User)session.get(user.class.userld.LockMode.UPGRADE);

       User.setName(“newName”);

       tx.commit();

 

                      B。乐观锁定

              乐观锁定乐观的认为资料的存取很少发生同时存取的问题,因而不作                            数据库层次上的锁定。为了维护正确的数据,乐观锁定使用应用程序上的                         逻辑实现版本控制的解决。通过version实现的乐观锁定机制是Hibernate                            官方推荐的乐观锁定实现,同时也是Hibernate中目前惟一在数据对象脱                               Session发生修改的情况下依然有效的锁机制。因此一般情况下都选择                       version方式作为Hibernate乐观锁定实现机制。

1.      使用版本检查

              <class name="bean.Login" table="login" schema="dbo" catalog="test" optimistic-lock=”version”>

                      <id name="id" type="java.lang.String">

            <column name="id" length="50" />

            <generator class="uuid.hex" />

            </id>

                      <version name="version" column=" version " type=”int”/>

                  <version>标签必须紧跟在<id>标签之后。

 

 

                              2.<version>控制的原理

                                   例:

              Team t1=(Team) session1.createQuery(“from s where s.age= 25 ). uniqueResault();

              Team t2=(Team) session2.createQuery(“from s where s.age= 25 ). uniqueResault();

       // 同时查询同一个数据,此时t1.getVersion()和t2.getVersion()是一样的,都是0

                            tx1=session.beginTransaction();

                            t1.setNname(“TOM”);

                            tx1.commit();

            //此时由于更新,数据库中的version变成了1

                            tx2=session.beginTransaction();

                            t2.setNname(“JACK”);

                            tx2.commit();

              //因为其版本号仍然是0,而数据库中版本号已变为1,所以更新失败,抛出异常

                           

                     注意:由于乐观锁定是使用系统程序来控制而不是数据库中的锁定机制,所以如果在上面第2个事务提交时加入t2.setVersion1);就不会有错误发生,设计时需要注意。

 

3.  Spring

spring学习文挡.doc

 

 

4.  Struts+Hibernate的实现

使用MyEclipse加载

新建一个WEB项目,并加载STRUTS框架,在此不做描述

1      在项目上点击右键选择MyEclipse加载Hibernate,如图

       

 

2)选择后出现下图

这里选择Hibernate的版本号和加载HibernateJAR

 

3)创建Hibernate配置文件

指定了配置文件的名称和位置

4)配置HibernateDataSource

DB Profile选项可以选择早先在MyEclipse DataBase视图中已建立好的DataSource

也可自己填写。

 

5)建立SessionFactory

 

点击Packages,选择SessionFactory类建立的位置完成加载

 

6)加载后生成hibernate.cfg.xml配置文件和SessionFactory

其中SessionFactory类中会自动生成currentSession()closeSession()方法,前者是获得一个Session,后者是关闭Session。在业务类中只需调用其方法即可:

        Session session = SessionFactory类名.currentSession();// 开启连接

最后事务提交后需要SessionFactory类名.closeSession();//关闭连接

               

         7)下面对数据库中的表进行映射配置

                     首先切换到MyEclipse DataBase视图,对目标数据库建立连接

                     选中要操作的表,右键选择“Creeate Hibernate Mapping

             

     8)选择数据库对应表生成的配置文件和实体Bean的位置,自动更新Hibernate的配置文件和生成Bean

                    

                    

9)指定表的主键生成方式,完成后对表的映射配置完成,生成表的配置文件和Bean

ID Generator的生成方式:一般情况,我们使用“native”或uuid.hex

assigned”

主键由外部程序负责生成,在 save() 之前指定一个。

 

hilo”

通过hi/lo 算法实现的主键生成机制,需要额外的数据库表或字段提供高位值来源。

 

seqhilo”

hilo 类似,通过hi/lo 算法实现的主键生成机制,需要数据库中的 Sequence,适用于支持 Sequence 的数据库,如Oracle

 

increment”

主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大值,之后每次需要生成主键的时候将此值加1作为主键。这种方式可能产生的问题是:不能在集群下使用。

 

identity”

采用数据库提供的主键生成机制。如DB2SQL ServerMySQL 中的主键生成机制。

 

sequence”

采用数据库提供的 sequence 机制生成主键。如 Oralce 中的Sequence

 

native”

Hibernate 根据使用的数据库自行判断采用 identityhilosequence 其中一种作为主键生成方式

 

uuid.hex”

Hibernate 基于8 UUID 算法 生成16 进制数值(编码后以长度32 的字符串表示)作为主键。

 

uuid.string”

uuid.hex 类似,只是生成的主键未进行编码(长度16),不能应用在 PostgreSQL 数据库中。

 

foreign”

使用另外一个相关联的对象的标识符作为主键。

 

          

          

10)对表的映射配置文件的一些说明

              <class name="bean.Login" table="login" schema="dbo" catalog="test">

              此行指定了Bean对应的数据库表

 

              <id name="id" type="java.lang.String">

            <column name="id" length="50" />

            <generator class="uuid.hex" />

        </id>

id指明了表中的主键及主键的生成方式,注意如果表中没有定义主键,则Hibernate会将所有列自动设置为复合主键。

 

id下添加<version name="version" column=" version "/>可以实现Habernate对数据库的乐观锁,但其一定要跟在<id></id>后,不能将其放到其他列之后声明

 

<property name="pwd" type="java.lang.String">

            <column name="pwd" length="50" />

</property>

普通列的声明

 

<set name="classTables" inverse="true" cascade="all">

        <key>

          <column name="StudentID" not-null="true" />

      </key>

         <one-to-many class="model.ClassTable" />

 </set>

如果有及联关系,配置如上

<set name="classTables" inverse="true" cascade="all">

生命了外键的来源,cascade="all"意思是如果更新或删除classTables表中的某条信息,则在本表中与其关联的数据也会自动更新或删除。

<key>

       <column name="StudentID" not-null="true" />

</key>

声明了本表中的外键。

 

    11)具体业务处理见DEMO

   

5.  Struts+Spring的实现

新建一个WEB项目,并加载STRUTS框架,在此不做描述

1)在项目上点击右键选择MyEclipse加载Spring,如图

 

 2)加载Spring所需的JAR

加载包时将其加载到lib文件夹下,否则发布或移动时会找不到所需的JAR

普通情况下只需要加载Core包,Spring联合Hibernate时需要加载DAO包。

推荐自己加载整合包,无须选择。

 

3)指定Spring配置文件的位置,加载完成

 

4)对一些配置文件的说明

StrutsSpring结合后,就由Spring来管理所有的Action

A.Struts配置文件说明

<action path="/Login"

         type="org.springframework.web.struts.DelegatingActionProxy"

         name="LoginForm"

        scope="request"         

        >

        红字部分声明了由Spring来管理Action

 

<plug-in className= "org.springframework.web.struts.ContextLoaderPlugIn">

<set-property property= "contextConfigLocation" value="/WEB-INF/classes/bean.xml"/>

    </plug-in>

      以上加载了Spring的配置文件,并由此配置文件来管理Action

      

B.Spring配置文件说明

           <bean id="dataSource"

        class="org.springframework.jdbc.datasource.DriverManagerDataSource">

        <property name="driverClassName">

            <value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>

        </property>

        <property name="url">

        <value>jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=test</value>

        </property>

        <property name="username">

            <value>sa</value>

        </property>

        <property name="password">

            <value></value>

        </property>

</bean>

声明了dataSource,相当于连接池

 

        <bean id="test" class="model.DB">

        <property name="dataSource">

            <ref bean="dataSource" />

        </property>

</bean>

数据库业务处理类,将上面定义的dataSource注入了model.DB类,在DB类中只需

private DataSource dataSource; 

public void setDataSource(DataSource dataSource) {

        this.dataSource = dataSource;

}

   setDataSource方法就能获得注入的dataSource

 

      <bean name="/Login" class="com.yourcompany.struts.action.LoginAction">

        <property name=" test ">

            <ref bean=" test " />

        </property>

    </bean>

   在页面中出现"/Login"   请求时会经过Struts-config里的配置转到此配置文件,当有相同的请求配置时调用对应的Action

把业务类注入Action类,在Action类中只需获得注入就可以调用其中的方法。

然后经由Action读取Struts-config配置里的ForwardMapping等方法返回页面。

 

5)具体实现流程见DEMO演示

 

 

6.  Struts+Hibernate+Spring的实现

 新建一个WEB项目,并加载STRUTS框架,在此不做描述

 按方法5加载Spring

 按方法4加载Hibernate,在第(3)步会出现

 

 

选择第2项则会把Hibernate配置自动写入Spring配置文件中,无须生成单独的Hibernate配置文件

 

第(4)步选择将Hibernate写入已有的Spring配置文件或是新建Spring配置文件,这里选择已有的写入

SessionFactory ID是定义<bean id=“的名称,内容是生成SessionFactory(取代Hibernate自动生成的SessionFactory类)

 

第(5)步定义DataSourceid和内容

    然后流程回到方法4的第5步,但这次不生成SessionFactory

完成后HibernateSpring加载完毕

添加表的映射见方法4

 

1)对一些配置文件的说明

  A.datasourcesessionFactory是自动生成,mappingResources下的表配置文件是自动添加的

         <bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource">

        <property name="driverClassName">

            <value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>

        </property>

        <property name="url">

        <value>jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=test</value>

        </property>

        <property name="username">

            <value>sa</value>

        </property>

    </bean>

<bean id="sessionFactory"

class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

        <property name="dataSource">

            <ref bean="datasource" />

        </property>

        <property name="hibernateProperties">

            <props>

                <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>

            </props>

        </property>

        <property name="mappingResources">

            <list>

                <value>Login.hbm.xml</value>

                <value>bean/Login.hbm.xml</value>

            </list>

        </property>

    </bean>

   

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">

       <property name="sessionFactory"><ref bean="sessionFactory"/></property>

</bean>

此项为手动添加,声明了事务管理以便于使用Hibernate的各种操作方法

 

       <bean id="login" class="bean.LoginDAO">

              <property name="sessionFactory"><ref local="sessionFactory"/></property>

       </bean>

       声明了数据库业务处理类,此类必须继承HibernateDaoSupport类,注入了sessionFactory自动获得Session,然后只需调用HibernateDaoSupport类中的静态方法对数据库进行操作即可。

 

           <bean id="userDAO"

      class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

              <property name="transactionManager"><ref local="transactionManager"/></property>

              <property name="target"><ref local="login"/></property>

              <property name="transactionAttributes">

                     <props>

                            <prop key="findAll">PROPAGATION_REQUIRED</prop>

                     </props>

              </property>

       </bean>

       此处声明了事务管理的具体类的具体方法

<property name="target"><ref local="login"/></property>

<prop key="findAll">PROPAGATION_REQUIRED</prop>

2句声明了对bean.LoginDAO中的findAll方法进行了事务管理,如方法中对数据库的操作出现了错误,则会对整个方法进行回滚操作。

 

2)具体实现流程见DEMO演示。

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值