首页 > 代码库 > SSH电力项目一 搭建Hibernate框架

SSH电力项目一 搭建Hibernate框架

Hibernate所需要的基本文件:

ElectText.java

ElecText.hbm.xml

hibernate.cfg.xml

 

第一步:创建测试表Elec_Text:

create table Elec_Text(textID varchar(50) not null primary key,textName varchar(50),textDate datetime,textRemark varchar(500) );

第二步:创建项目,导入jar包

 

第三步:持久层

(1)在com.elec.domain中创建ElecText.java

ElecText.java  说明:持久层要实现一个序列化接口:Serializable

public class ElecText implements java.io.Serializable {
    
    private String textID;        //主键ID
    private String textName;      //测试名称
    private Date textDate;        //测试日期
    private String textRemark;    //测试备注
    
    public String getTextID() {
        return textID;
    }
    public void setTextID(String textID) {
        this.textID = textID;
    }
    public String getTextName() {
        return textName;
    }
    public void setTextName(String textName) {
        this.textName = textName;
    }
    public Date getTextDate() {
        return textDate;
    }
    public void setTextDate(Date textDate) {
        this.textDate = textDate;
    }
    public String getTextRemark() {
        return textRemark;
    }
    public void setTextRemark(String textRemark) {
        this.textRemark = textRemark;
    }
}

在com.elec.domain目录下,创建ElecText.java对应的映射文件  ElecText.hbm.xml

到对应的jar包中找到约束,复制到配置文件中:

<?xml version="1.0" encoding="UTF-8" ?>
<!-- 打开hibernate包,找到约束文件 -->
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 有了约束,就可以写mapping -->
<hibernate-mapping>
    <class name="com.kangjie.elec.domain.ElecText" table="Elec_Text"><!-- name是类型 ,在类名上按F2选中全路径名-->
        <id name="textID" type="string" column="textID">
            <generator class="uuid"></generator>
        </id>
        <property name="textName" type="string" column="textName"></property>
        <property name="textDate" type="date" column="textDate"></property>
        <property name="textRemark" type="string" column="textRemark"></property>
    </class>
</hibernate-mapping>
<!-- 然后写映射文件 -->

(3) 在工程下创建文件夹config,config下创建hibernate.cfg.xml的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!-- 添加约束 -->
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
    <!-- 连接数据库信息 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/kangjie?useUnicode=true&amp;characterEncoding=utf8</property>
        <property name="hibernate.connection.username">admin</property>
        <property name="hibernate.connection.password">admin</property>
        <!-- 其他配置 --><!--  测试业务层的时候,不用自动提交 -->
        <property name="hibernate.connection.autocommit">true</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <property name="hibernate.hbm2ddl.auto">update</property><!-- 没有表就自动创建 -->
        <property name="hibernate.show_sql">true</property>
        <!-- 添加映射 -->
        <mapping resource="com/kangjie/elec/domain/ElecText.hbm.xml"/>
        <!-- 修改了项目名称,可以还需要修改myeclipse下的web选项的名称 -->
    </session-factory>

</hibernate-configuration>

(4) 使用junit在test包中进行测试(并且导入log4j的配置文件)

public class TestHibernate {
/**
 * 测试保存
 */
    @Test
    public void save(){
        Configuration configuration = new Configuration();
        configuration.configure();//加载classpath下的hibernate.cfg.xml文件
        SessionFactory sf = configuration.buildSessionFactory();
        Session s = sf.openSession();
        Transaction ts = s.beginTransaction();
        
        ElecText elecText = new ElecText();
        elecText.setTextName("测试数据");
        elecText.setTextDate(new Date());
        elecText.setTextRemark("备注");
        s.save(elecText);
        ts.commit();
        s.close();
        /**
         * 测试的过程中可能会有日志警告,因为hibernate需要配置log4j日志
         */
    }
}

然后添加log4j.propertities

技术分享

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file hibernate.log ###
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=hibernate.log
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change ‘info‘ to ‘debug‘ ###

log4j.rootLogger=error, stdout

#log4j.logger.org.hibernate=info
#log4j.logger.org.hibernate=debug

### log HQL query parser activity
#log4j.logger.org.hibernate.hql.ast.AST=debug

### log just the SQL
#log4j.logger.org.hibernate.SQL=debug

### log JDBC bind parameters ###
#log4j.logger.org.hibernate.type=info
#log4j.logger.org.hibernate.type=debug

### log schema export/update ###
#log4j.logger.org.hibernate.tool.hbm2ddl=debug

### log HQL parse trees
#log4j.logger.org.hibernate.hql=debug

### log cache activity ###
#log4j.logger.org.hibernate.cache=debug

### log transaction activity
#log4j.logger.org.hibernate.transaction=debug

### log JDBC resource acquisition
#log4j.logger.org.hibernate.jdbc=debug

### enable the following line if you want to track down connection ###
### leakages when using DriverManagerConnectionProvider ###
#log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace

 

 测试结果:

技术分享

数据库中的显示

 技术分享

 

 

第四步:DAO层

每个持久化对象都会对应一个Dao,都有操作单标的CRUD的操作;为了避免重复,抽取一个公用的Dao:CommonDao

技术分享

 

(1) 在com.elec.dao中创建2个接口(公用接口和业务接口)

 * 公共接口

public interface ICommonDao<T> {
    void save(T entity);
}

 * 业务接口(需要继承公共接口,并且指定泛型T所对应的对象:

/**
 * 每个持久化对象都会对应一个Dao,都有操作单单表的CRUD:create , Retrieve,update,delete
 *
 */
public interface IElecTextDao extends ICommonDao<ElecText>{
    public static final String SERVICE_NAME="com.kangjie.elec.dao.impl.ElecTextDaoImpl";
}

(2)在com.elec.dao.impl中创建2个接口的实现类

* 公用类(需要继承HibernateDaoSupport,这样可以方便使用HibernateTemplate对象):

public class CommonDaoImpl<T> extends HibernateDaoSupport implements ICommonDao<T> {

    /**
     * 使用hibernate模板保存:
     */
    @Resource(name="sessionFactory")
    public void setDi(SessionFactory sessionFactory){
        System.out.println("sessionFactory" + sessionFactory);
        this.setSessionFactory(sessionFactory);
    }
    
    public void save(T entity) {
        this.getHibernateTemplate().save(entity);
    }

}

*  业务类(需要继承公用类,这样可以使用公用类中的定义的方法)

/**
* spring容器:
* * 创建Action,Service,Dao的对象(IOC)
* * * <bean id="" class=""></bean>
* * 每层进行注入(DI)
* ** <property name="" ref=""/>
* * 声明式事务(AOP)切面编程
* **** 声明事务管理器
* * 电力项目(注解方式)
* * @Controller @Service , @Repository @Commponent
*
*/
//注解支持
/**
* 相当于正在spring容器中定义:
* <bean id="elecTextDaoImpl" class="com.itheima.elec.dao.impl.ElecTextImpl">
*这种写法过于繁琐,在接口IElecTextDao中指定 标示 public static final String SERVICE_NAME="com.kangjie.elec.dao.impl.ElecTextDaoImpl";


*/
//唯一的属性
@Repository(IElecTextDao.SERVICE_NAME)
public class ElecTextDaoImpl extends CommonDaoImpl<ElecText> implements IElecTextDao {

}

(3) 在config中创建spring的配置文件(beans.xml)

<beans  xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
                            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                            http://www.springframework.org/schema/context 
                            http://www.springframework.org/schema/context/spring-context-3.0.xsd
                            http://www.springframework.org/schema/tx 
                            http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
                            http://www.springframework.org/schema/aop 
                            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 
<!-- 1.添加组件对注解的支持 :表示这个包下都支持注解 -->                            
<context:component-scan base-package="com.kangjie.elec"/>    
<!--  -->

<!-- 3.spring整合hibernate的核心:session工厂 -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <!-- 注入资源 -->
    <property name="configLocation">
        <value>
            classpath:hibernate.cfg.xml
        </value>
    </property>
</bean>
<!-- 4.创建事务管理器 :管理session工厂,即:hibernate -->
<bean id="trManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<!-- 注入 sessionfactory -->
    <property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 5:事务处理     注解,在Service层填写一个注解@Transcational -->
<tx:annotation-driven transaction-manager="trManager" />
<!--下边这部分是设置配置文件,只做演示--> <!-- 事务处理配置文件--> <!-- <tx:advice id="aa" transaction-manager="trManager"> <tx:attributes> <tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/> <tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/> <tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/> <tx:method name="*" read-only="false"/> </tx:attributes> </tx:advice> <aop:config> --> <!-- * com.itheima.elec.service..* .* (..) --> <!-- 返回任意类型 service包及其子包 中所有类, 类中所有方法 参数任意--> <!-- <aop:pointcut expression="execution(* com.kangjie.elec.service..*.*(..))" id="bb"/> <aop:advisor advice-ref="aa" pointcut-ref="bb"/> </aop:config> --> </beans>

技术分享

技术分享

 

 

(4) 使用junit完成测试

public class TestDao {

    //保存
    @Test
    public void save(){
        //加载spring容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        IElecTextDao elecTextDao = (IElecTextDao) ac.getBean(IElecTextDao.SERVICE_NAME);//找节点
        ElecText elecText = new ElecText();
        elecText.setTextName("abcde");
        elecText.setTextDate(new Date());
        elecText.setTextRemark("make a difference");
        elecTextDao.save(elecText);
    }
}

注意:如果数据没有保存,需要设置事务自动提交:在hibernate.cfg.xml中添加:

<!-- 使用hibernate的方式提交事务(自动提交) -->
<property name="hibernate.connection.autocommit">true</property>

 

第五步:Service层

(1) 在com.elec.service中创建接口:

public interface IElecTextService {
    public static final String SERVICE_NAME="com.kangjie.elec.service.impl.ElecTextServiceImpl";

    public void saveElecText(ElecText elecText);
}

 

(2) 在com.elec.service.impl中创建接口的实现类:

/**
 * spring框架使用的是分层的注解
* @Repository 持久层
* @Service 服务层
* @Controller 控制层
* 在Service层添加注解: @Transactional
*
* @Service *相当于在spring中定义: * <bean id ="" class="">
*/ @Service(IElecTextService.SERVICE_NAME) @Transactional(readOnly=true) //由于spring提供的声明式事务处理,进行事务的控制,在业务层的类和方法上定义@Transactional(),同时去掉hibernate.cfg.xml中的配置,由spring统一控制。 public class ElecTextServiceImpl implements IElecTextService { @Resource(name=IElecTextDao.SERVICE_NAME) IElecTextDao elecTextDao;
/*
由于spring提供的声明式事务处理,进行事务的控制,在业务层的类和方法上定义@Transactional(),同时去掉hibernate.cfg.xml中的配置,由spring统一控制。去掉的代码是

           <!-- 使用hibernate的方式提交事务(自动提交) -->

           <property name="hibernate.connection.autocommit">true</property> 

      */

    @Override
    @Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,readOnly=false)
    public void saveElecText(ElecText elecText) {
        elecTextDao.save(elecText);
        //然后测试
    }

}

 

(3) 测试

public class TestService {

    @Test
    public void save(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        IElecTextService elecTextService = (IElecTextService)ac.getBean(IElecTextService.SERVICE_NAME);
        
        ElecText elecText = new ElecText();
        elecText.setTextName("测试service名称3");
        elecText.setTextDate(new Date());
        elecText.setTextRemark("备注service3");
        elecTextService.saveElecText(elecText);
    }
}

 

由于spring提供的声明式事务处理,进行事务的控制,在业务层的类和方法上定义@Transactional(),同时去掉hibernate.cfg.xml中的配置,由spring统一控制。去掉的代码是:

<!-- 使用hibernate的方式提交事务(自动提交) -->
<property name="hibernate.connection.autocommit">true</property>

第六步:

(1)在com.elec.web.action中创建Action(业务Action)类和BaseAction(公用Action)

Action类:(注意:这里要设置成多例,即@Scope(value=http://www.mamicode.com/prototype),因为struts2的Action是多实例,多线程)

struts2是模型驱动  ?

 

@SuppressWarnings("serial")
@Controller("elecTextAction")
@Scope(value="prototype")
public class ElecTextAction extends ActionSupport implements ModelDriven<ElecText>{

    ElecText elecText = new ElecText();
    
    //注入Service
    @Resource(name=IElecTextService.SERVICE_NAME)
    IElecTextService elecTextService;
    
    
    //执行保存
    public String save(){
        elecTextService.saveElecText(elecText);
        return "save";
    }

    @Override
    public ElecText getModel() {
        
        // TODO Auto-generated method stub
        return elecText;
    }
}

然后将复用的内容抽取为一个公用类BaseAction类 

package com.elec.web.action;

import java.lang.reflect.ParameterizedType;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public class BaseAction<T> extends ActionSupport implements ModelDriven<T> {

T entity;
// T型实例化
public BaseAction(){
//T型转换
// this.getClass().getGenericSuperclass();
ParameterizedType parameterizedType = (ParameterizedType) this.getClass().getGenericSuperclass();
Class entityClass = (Class) parameterizedType.getActualTypeArguments()[0] ;
try {
    entity = (T) entityClass.newInstance();
} catch (Exception e) {
    e.printStackTrace();
}
}
@Override
public T getModel() {
    return entity;
}

}

 

断点调试,使用watch查看this.Class的值 : 

技术分享

继续查看

技术分享

技术分享

转换成功

 

 

首先

在com.elec.util包下创建公用类(用于泛型转换)。

泛型转换的目的子类传递真实对象类型,在父类中使用泛型转换成真实对象类型。

以后util包下封装的就是公用类。

package com.elec.utils;

import java.lang.reflect.ParameterizedType;

public class TUtils {

    public static Class getActualType(Class entity){
        ParameterizedType parameterizedType = (ParameterizedType) entity.getGenericSuperclass();
        Class entityClass = (Class) parameterizedType.getActualTypeArguments()[0];
        return entityClass;
    }
}

 然后抽取BaseAction类,调用TUtils中的方法 

BaseAction.java

package com.elec.web.action;
public class BaseAction<T> extends ActionSupport implements ModelDriven<T>,ServletRequestAware,ServletResponseAware{ T entity; protected HttpServletRequest request; protected HttpServletResponse response; // protected HttpServletRequest request; //实例化泛型 public BaseAction(){ //T型转换 Class entityClass = TUtils.getActualType(this.getClass()); try { entity = (T) entityClass.newInstance(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public T getModel(){ return entity; } @Override public void setServletResponse(HttpServletResponse response) { // TODO Auto-generated method stub this.response = response; } @Override public void setServletRequest(HttpServletRequest request) { // TODO Auto-generated method stub this.request = request; } }

 

ElecTextAction.java  继承BaseAction

package com.elec.web.action;

@SuppressWarnings("serial")
@Controller("elecTextAction")
@Scope(value="prototype")
public class ElecTextAction extends BaseAction<ElecText>{

    ElecText elecText = this.getModel();
    
    //注入Service
    @Resource(name=IElecTextService.SERVICE_NAME)
    IElecTextService elecTextService;
    
    
    //执行保存
    public String save(){
        elecTextService.saveElecText(elecText);
        String textDate = request.getParameter("textDate");
        System.out.println(textDate);
        return "save";
    }

}

 

创建struts2的配置文件struts.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <!-- 开发模式 -->
    <constant name="struts.devMode" value="http://www.mamicode.com/true"></constant>
    <!-- ui主题,简单主题 -->
    <constant name="struts.ui.theme" value="http://www.mamicode.com/simple"></constant>
    <!-- 修改struts的后缀 改成do -->
    <constant name="struts.action.extension" value="http://www.mamicode.com/do"></constant>
    
    <!-- 系统管理 -->
    <package name="system" namespace="/system" extends="struts-default">
        <!-- 测试 -->
        <action name="elecTextAction_*" class="elecTextAction" method="{1}">
                <result name="save">/system/textAdd.jsp</result>
        </action>
    </package>
</struts>

在web.xml中添加配置:

 

<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name></display-name>    
    <!-- 配置struts2的过滤器,这是struts2运行的核心 -->
    <filter>
        <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- web容器启动的时候,自动加载spring容器(监听器) -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:beans.xml</param-value>
    </context-param>
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

 

 测试页面:

 textAdd.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
   <script type="text/javascript" src="http://www.mamicode.com/${pageContext.request.contextPath}/My97DatePicker/WdatePicker.js"></script>
<html>
<head>
<title>测试专用jsp</title>
<link href="http://www.mamicode.com/${pageContext.request.contextPath }/css/Style.css" type="text/css" rel="stylesheet">

  <script language="javascript"> 
   function checkchar(){
          document.Form1.action="${pageContext.request.contextPath }/system/elecTextAction_save.do";
          document.Form1.submit();
  }
  function addEnter(element){
   document.getElementById(element).value = document.getElementById(element).value+"<br>";
   
  }
  </script>


</head>

<body>
<form name="Form1" id="Form1" method=post>

    <table cellspacing="1" cellpadding="5" width="90%" align="center" bgcolor="#f5fafe" style="border:1px solid #8ba7e3" border="0">

        <tr>
            <td class="ta_01" colspan=2 align="center" background="${pageContext.request.contextPath }/images/b-info.gif">
            <font face="宋体" size="2"><strong>测试专用jsp</strong></font>
            </td>
        </tr>
        <TR height=10><td></td><td></td></TR>
        
        <tr>
            <td class="ta_01" align="center" bgcolor="#f5fafe" width="15%">测试名称:</td>
            <td class="ta_01" bgcolor="#ffffff" style="word-break: break-all">
    
            <textarea name="textName" id="textName"   style="width: 500px; height: 160px; padding: 1;FONT-FAMILY: 宋体; FONT-SIZE: 9pt" onkeydown="if(event.keyCode==13)addEnter(‘textName‘);"></textarea>
            </td>
            
        </tr>
        <tr>
            <td class="ta_01" align="center" bgcolor="#f5fafe" width="15%">测试日期:</td>
            <td class="ta_01" bgcolor="#ffffff" style="word-break: break-all">
    
            <input name="textDate" type="text" maxlength="50" size=20 onclick="WdatePicker()">
            </td>
            
        </tr>
        <tr>
            <td class="ta_01" align="center" bgcolor="#f5fafe" width="15%">测试备注:</td>
            <td class="ta_01" bgcolor="#ffffff" style="word-break: break-all">
            <textarea name="textRemark" id="textRemark"  style="width: 500px; height: 160px; padding: 1;FONT-FAMILY: 宋体; FONT-SIZE: 9pt" onkeydown="if(event.keyCode==13)addEnter(‘textRemark‘);"></textarea>
            </td>
            
        </tr>
        <tr>
            <td class="ta_01" style="width: 100%" align="center" bgcolor="#f5fafe" colspan="2">
            <input type="button" name="BT_Submit" value="http://www.mamicode.com/保存" onclick="checkchar()" id="BT_Submit" style="font-size:12px; color:black; height=20;width=50">
            </td>
        </tr>
    </table>
      
</form>

</body>
</html>

 实现ServletRequestAware,ServletResponseAware报错:

can not implement the missing methods,either due to compile errors or the projects build path does not resolve all dependencies

上面的错误提示的意思是:不能实现丢失的方法,或许是因为编译错误或者工程创建的路径不能解决所有依赖;也就是缺少Servlet相关的jar包了,这里是servlet-api.jar

解决办法:添加servlet-api.jar。

这个jar包可以在tomcat的lib目录下找到,复制到项目中去就可以了

 

SSH电力项目一 搭建Hibernate框架