欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

spring结合hibernate示例详解

程序员文章站 2024-02-29 20:51:16
单纯hibernate程序 1、首先是导入hibernate的jar包。 2、 建立用户和用户操作记录实体,log.java和user.java。代码如下所示...

单纯hibernate程序

1、首先是导入hibernate的jar包。

2、 建立用户和用户操作记录实体,log.java和user.java。代码如下所示。

log.java

import java.util.date; 
public class log { 
  private int id; 
  //日志的类别.日志一般起到一个不可否认性. 
  //操作日志 安全日志 事件日志. 
  private string type; 
  private string detail; 
  private date time; 
  public int getid() { 
    return id; 
  } 
  public void setid(int id) { 
    this.id = id; 
  } 
  public string gettype() { 
    return type; 
  } 
  public void settype(string type) { 
    this.type = type; 
  } 
  public string getdetail() { 
    return detail; 
  } 
  public void setdetail(string detail) { 
    this.detail = detail; 
  } 
  public date gettime() { 
    return time; 
  } 
  public void settime(date time) { 
    this.time = time; 
  } 
} 

user.java

public class user { 
  private int id; 
  private string name; 
  public int getid() { 
    return id; 
  } 
  public void setid(int id) { 
    this.id = id; 
  } 
  public string getname() { 
    return name; 
  } 
  public void setname(string name) { 
    this.name = name; 
  } 
} 

3、 并建立与之对应的实体配置文件,log.hbm.xml和use.hbm.xml。代码如下所示。

<?xml version="1.0"?> 
<!doctype hibernate-mapping public  
  "-//hibernate/hibernate mapping dtd 3.0//en" 
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping> 
  <class name="com.bjpowernode.usermgr.domain.user" table="t_user"> 
    <id name="id" > 
      <generator class="native"/> 
    </id> 
    <property name="name" /> 
  </class> 
</hibernate-mapping> 

log.hbm.xml

<?xml version="1.0"?> 
<!doctype hibernate-mapping public  
  "-//hibernate/hibernate mapping dtd 3.0//en" 
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping> 
  <class name="com.bjpowernode.usermgr.domain.log" table="t_log"> 
    <id name="id" > 
      <generator class="native"/> 
    </id> 
    <property name="type" /> 
    <property name="detail" /> 
    <property name="time" /> 
  </class> 
</hibernate-mapping> 

4、manager层代码如下所示。

logmanager.java接口

public interface logmanager { 
  //添加日志.方法 
  public void addlog(log log); 
} 

logmanagerimpl实现

public class logmanagerimpl implements logmanager { 
  @override 
  public void addlog(log log) {  
    hibernateutils.getsessionfactory().getcurrentsession().save(log); 
     
  } 
}

usermanager接口

public interface usermanager { 
 
  public void adduser(user user); 
} 

usermanagerimpl.java实现

public class usermanagerimpl implements usermanager { 
  @override 
  public void adduser(user user) { 
    session session = null; 
    try { 
      //这个session中是放到threadlocal. 
      session = hibernateutils.getsessionfactory().getcurrentsession(); 
      session.begintransaction(); 
      // 网用户表中添加一条同时网日志中添加一条. 
      session.save(user); 
      log log = new log(); 
      log.settype("操作日志"); 
      log.settime(new date()); 
      log.setdetail("xxx"); 
      logmanager logmanager = new logmanagerimpl(); 
      //添加日志. 
      logmanager.addlog(log); 
      session.gettransaction().commit(); 
    } catch (exception e) { 
      e.printstacktrace(); 
      session.gettransaction().rollback(); 
    }finally{ 
      hibernateutils.closesession(session); 
    } 
  } 
} 

5、是通过sessionfactory来创建session,通过session来开启提交和关闭回滚事务,我们把session的开启关闭封装到一个工具类中。hibernateutils.java代码如下所示。

public class hibernateutils { 
  private static sessionfactory factory; 
  static { 
    try { 
      //读取hibernate.cfg.xml文件 
      configuration cfg = new configuration().configure(); 
      //建立sessionfactory 
      factory = cfg.buildsessionfactory(); 
    }catch(exception e) { 
      e.printstacktrace(); 
    } 
  } 
  public static session getsession() { 
    return factory.opensession(); 
  }  
  public static void closesession(session session) { 
    if (session != null) { 
      if (session.isopen()) { 
        session.close(); 
      } 
    } 
  } 
  public static sessionfactory getsessionfactory() { 
    return factory; 
  } 
} 

6、配置hibernate.cfg.xml文件,包括数据库名称,数据库关联的表,以及用户名密码等。代码如下所示。

<hibernate-configuration> 
  <session-factory> 
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.driver</property> 
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/spring_hibernate_1</property> 
    <property name="hibernate.connection.username">root</property> 
    <property name="hibernate.connection.password">root</property> 
    <property name="hibernate.dialect">org.hibernate.dialect.mysqldialect</property> 
    <property name="hibernate.show_sql">true</property> 
    <property name="hibernate.hbm2ddl.auto">update</property> 
    <property name="hibernate.current_session_context_class">thread</property> 
    <!--  
    <property name="hibernate.current_session_context_class">jta</property> 
    --> 
    <mapping resource="com/bjpowernode/usermgr/domain/user.hbm.xml"/> 
    <mapping resource="com/bjpowernode/usermgr/domain/log.hbm.xml"/> 
  </session-factory> 
</hibernate-configuration> 

7、 使用junit进行单元测试,代码如下所示。

import junit.framework.testcase; 
public class usermanagerimpltest extends testcase { 
  public void testadduser() { 
    usermanager usermanager = new usermanagerimpl(); 
    user user = new user(); 
    user.setname("张三"); 
    usermanager.adduser(user); 
  } 
} 

在上述操作用,对事物的控制边界在业务逻辑层,因为在usermanagerimpl中我们调用adduser()这一方法的同时要把这一操作写入到日志中,也就是调用了addlog()方法,而对于类的方法,一方法一session,一session一事务,那么如果控制事务的呢?我们要执行开启adduser()事务同时再开启addlog()事务吗?在这里我们没有再用以前的opensession方法,选择用的hibernateutils.getsessionfactory().getcurrentsession();同时在hibernate.cfg.xml中对getcurrentsession()进行配置如下,       <propertyname="hibernate.current_session_context_class">thread</property>表示在当前线程中,与当前线程绑定这样执行adduser()方法和addlog()方法使用的是同一个事务。

那opensession和getcurrentsession的区别呢?

1、          opensession必须关闭,currentsession在事务结束后自动关闭。

2、          opensession没有和当前线程绑定,currentsession和当前线程绑定。并且使用currentsession需要在我们的hibernate.cfg.xml文件中进行事务的配置,是使用jdbc事务还是jta事务。

hibernate和spring结合使用

我们从上述例子中发现,hibernate的事务是独立于hibernate对数据库的增删改查的,并且事务控制在我们的业务逻辑层,对于独立的东西,像是横切性问题,自然想到了aop,实际上springaop封装了对事务的管理,使用springaop我们不再负责去开启和关闭事务。

下面用springaop来和hibernate结合。

当然也要导入spring相关jar。

对于事务管理就是一个横切性问题,把事务管理模块化就是我们的aspect,然后再配置文件中进行配置,我们可以把事务单独放到一个配置文件中。

1、代码如下,applicationcontext-common.xml文件。

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" 
     xmlns:aop="http://www.springframework.org/schema/aop" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd 
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> 
  <!-- 配置sessionfactoyr --> 
  <bean id="sessionfactory" class="org.springframework.orm.hibernate3.localsessionfactorybean"> 
    <property name="configlocation"> 
      <value>classpath:hibernate.cfg.xml</value> 
    </property> 
  </bean> 
  <!-- 配置事务管理器 --> 
  <bean id="transactionmanager" class="org.springframework.orm.hibernate3.hibernatetransactionmanager"> 
    <property name="sessionfactory"> 
      <ref bean="sessionfactory"/> 
    </property> 
  </bean> 
<!-- 哪些类哪些方法使用事务. -->  
<aop:config> 
  <aop:pointcut id="allmanagermethod" expression="execution(* com.bjpowernode.usermgr.manager.*.*(..))"/> 
  <aop:advisor pointcut-ref="allmanagermethod" advice-ref="txadvice"/> 
</aop:config> 
<tx:advice id="txadvice" transaction-manager="transactionmanager"> 
  <tx:attributes> 
    <tx:method name="add*" propagation="required"/> 
    <tx:method name="del*" propagation="required"/> 
    <tx:method name="modify*" propagation="required"/> 
    <tx:method name="*" propagation="required" read-only="true"/> 
  </tx:attributes> 
</tx:advice> 
</beans> 

首先是配置的是sessionfactory,让spring拿到hibernate的sessionfactory,以便对hibernate事务控制,通过sessionfactory产生session再访问。这样就把把hibernate的sessionfactory注入到spring中了。通过<property>标签,告诉springhibernate的配置文件在哪里,以便spring可以读取hibernate的配置文件。
其次是配置事务管理器,把我们的sessionfactory注入给事务管理器,让事务管理器管理事务。

其次,到底是哪些类哪些方法,开始执行的时候执行事务,<aop:pointcutid="allmanagermethod"  

其次,配置aop,expression="execution(*com.bjpowernode.usermgr.manager.*.*(..))",到底是哪些类交给spring完成事务管理?我们应用在所有的manager包中的所有方法上,manager所有类所有方法全部参与事务的运行。那在什么地方触发开启事务?

再次,定义一个advice,配置事务的传播特性,例如adduser()中调用addlog()方法,是在同一个事务还是不在同一个事务。以add开头,del开头,modify开头以及其他,我们配置的事务传播特性为propagation="required",这样在一个方法中调用另一个方法他们公共一个线程。

2、让usermanagerimpl继承spring提供的对hibernatedao支持类。

hibernatedaosupport,这样继承之后我们就能拿到session,其实也就是hibernate中的session,只不过spring为我们封装了。我们可以这样拿到sesion:this.getsession().save(user);或者使用spring封装好的对象:

this.gethibernatetemplate().save(user);这样都封装到里面了,我们不管理事务的开启和关闭。

之前在我们的usermanagerimpl中使用了logmanagerimpl实例,这次我们可以使用spring的ioc容器,把他们之间的依赖关系注入到spring中,这样就看不到实例,面对接口编程,进行了解耦。

接口不变,usermanagerimpl.java代码如下所示。

public class usermanagerimpl extends hibernatedaosupport implements usermanager { 
  private logmanager logmanager; 
  public void setlogmanager(logmanager logmanager) 
  { 
    this.logmanager = logmanager; 
  } 
  @override 
  public void adduser(user user)throws exception { 
    //this.getsession().save(user); 
        //或者用. 
        this.gethibernatetemplate().save(user); 
        log log = new log(); 
        log.settype("操作日志"); 
        log.settime(new date()); 
        log.setdetail("xxx"); 
        //logmanager logmanager = new logmanagerimpl(); 
        //添加日志. 
        logmanager.addlog(log);        
        //运行期的异常,会回滚. 并且是他的子类也会回滚. 
        //throw new runtimeexception(); 
        //throw new exception(); 
  } 
} 

logmanagerimpl.java 代码如下所示。

public class logmanagerimpl extends hibernatedaosupport implements logmanager { 
  @override 
  public void addlog(log log) { 
    //getsession().save(log); 
    this.gethibernatetemplate().save(log); 
     
  } 
} 

删除我们自己建立的hibernateutils.java类,删除hibernate.cfg.xml文件中对getcurrentsession()的事务配置。

3、在配置文件中配置依赖关系。

applicationcontext-beans.xml代码如下所示。

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" 
     xmlns:aop="http://www.springframework.org/schema/aop" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd 
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> 
  <bean id="usermanager" class="com.bjpowernode.usermgr.manager.usermanagerimpl"> 
    <property name="sessionfactory" ref="sessionfactory"/> 
    <property name="logmanager" ref="logmanager"/> 
  </bean> 
  <bean id="logmanager" class="com.bjpowernode.usermgr.manager.logmanagerimpl"> 
    <property name="sessionfactory" ref="sessionfactory"/> 
  </bean> 
</beans> 

在junit中测试程序代码如下所示。

public class usermanagerimpltest extends testcase { 
  public void testadduser() { 
    beanfactory factory = new classpathxmlapplicationcontext("applicationcontext-*.xml");  
    usermanager usermanager = (usermanager) factory.getbean("usermanager"); 
    user user = new user(); 
    user.setname("张三"); 
    try { 
      usermanager.adduser(user); 
    } catch (exception e) { 
      e.printstacktrace(); 
    } 
  } 
} 

显示结果如下图所示。

spring结合hibernate示例详解

    这样就完成了spring和hibernate的结合,主要是利用springaop对hibernate的事务进行控制和在manager层之间的调用用spring ioc进行控制。

总结

以上所述是小编给大家介绍的spring结合hibernate示例详解,希望对大家有所帮助