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 voidsetTextID(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&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:事務處理 註解,[email protected] --> <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提供的聲明式事務處理,進行事務的控制,[email protected](),同時去掉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類:(註意:這裏要設置成多例,[email protected](value=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="true"></constant> <!-- ui主題,簡單主題 --> <constant name="struts.ui.theme" value="simple"></constant> <!-- 修改struts的後綴 改成do --> <constant name="struts.action.extension" value="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="${pageContext.request.contextPath}/My97DatePicker/WdatePicker.js"></script> <html> <head> <title>測試專用jsp</title> <link href="${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="保存" 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框架