关于使用Spring和hibernate开发web程序的配置说明和简单实例的详细说明
作者:yanek
email:yanek@126.com
一、实现目标:
通过使用spring和hibernate,实现用户的添加功能。把用户信息加入到数据库中
使用Spring 的hibernate模板实现DAO操作。
最终效果: 浏览器中输入 http://localhost:8083/hibernateTestWeb/user.do 数据库就增加一条记录。
二、分层结构
系统采用如下分层结构
1.WEB层:用户界面层 采用spring WEB MVC框架实现
2 SERVICE层:业务逻辑层 包括业务接口和实现类组成
3.DAO层: 数据访问层 包括数据访问接口和实现类组成
4.持久层:使用hibernate实现 使用hibernate实现数据库的访问。实现DAO接口。
三、数据库结构
数据库结构:USER_TABLE 表
建表sql语句
create table USER_TABLE
(
ID VARCHAR2(255) not null,
USERNAME VARCHAR2(20),
PASSWORD VARCHAR2(20)
)
假设使用的是数据库:oracle9i
用户名 密码为test/1234
四、系统设计的相关类及其层次结构
1. User.java 表示用户实体的值对象类,与数据库用户表结构相对应,标准的javabean,提供setter和getter方法。
2. UserDAO.java DAO接口
3. UserDAOImp.java DAO接口的实现类
4. UserService 业务逻辑层的接口
5. UserServiceImp 业务逻辑层的接口的实现类,调用DAo接口实现业务逻辑。
6. UserController web层客户调用层,调用业务逻辑层,实现对业务逻辑的处理。(前台)
五、相关配置文件:(重点,问题出错的地方)
包括Spring 的配置文件和hibernate配置文件,以及web.xml文件
说明:
web.xml,applicationContext.xml,SpringhibernateStudy-servlet.xml都在WEB-INF根目录下,映射文件在与实体类相同的目录下
1.Spring 的配置文件:
这里配置文件包括两个:
1.applicationContext.xml 对数据源,事务,事务代理,DAO ,Service层类进行定义和配置
内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- 下面定义数据库的连接信息,使用类为org.apache.commons.dbcp.BasicDataSource-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@192.168.1.191:1521:yanek</value>
</property>
<property name="username">
<value>test</value>
</property>
<property name="password">
<value>1234</value>
</property>
</bean>
<!-- 下面定义sessionFactory来为创建session做准备-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource" />
</property>
<property name="mappingResources">
<list>
<value>apps/hibernatetest/ioc/User.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">net.sf.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
</props>
</property>
</bean>
<!-- 下面定义hibernate模板 -->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate.HibernateTemplate">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<!-- 下面定义用户定义的DAO,指定了DAO的实现类,dao实现引用到hibernate模板-->
<bean id="UserDAO" class="apps.hibernatetest.ioc.UserDAOImp">
<property name="hibernateTemplate">
<ref local="hibernateTemplate" />
</property>
</bean>
<!-- 下面定义事务管理器类,引用到sessionFactory-->
<bean id="mytransactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
<!-- 下面定义事务代理工厂类类,引用到事务管理器,指定调用方法使用事务处理的匹配规则-->
<bean id="MyTransactionProxyFactory" abstract="true" lazy-init="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref local="mytransactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="user*">PROPAGATION_REQUIRED</prop>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="del*">PROPAGATION_REQUIRED</prop>
<prop key="up*">PROPAGATION_REQUIRED</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="dis*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<!-- 下面定义业务逻辑类,引用到事务管理器,通过已经定义的DAO来自动注入业务逻辑类引用的DAO类-->
<bean id="userService" parent="MyTransactionProxyFactory">
<property name="target">
<bean class="apps.hibernatetest.ioc.UserServiceImp">
<property name="userDAO"><ref local="UserDAO"/></property>
</bean>
</property>
</bean>
</beans>
2.SpringhibernateStudy-servlet.xml 主要对mvc web层的javabean定义
注意:这里名称要与在web.xml中对org.springframework.web.servlet.DispatcherServlet的对应servlet名称对应。
这里web.xml文件里配置了名字为SpringhibernateStudy,所以文件名必须为:SpringhibernateStudy-servlet.xml
格式:servlet名称+-servlet.xml
如果配置名称为SpringServlet则,配置文件应该为:SpringServlet-servlet.xml
内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<!-- - Application context definition for "springapp" DispatcherServlet. -->
<beans>
<!-- 下面定义web层控制器类,引用到业务处理类,通过已经定义的service类来自动注入web控制器引用的service类-->
<bean id="UserController" class="apps.hibernatetest.ioc.UserController">
<property name="userService">
<ref bean="userService" />
</property>
</bean>
<!-- 下面定义web层请求访问路径和控制器类的影射关系以及对请求方式处理类的类配置的方法-->
<bean id="UserurlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/user.do">UserController</prop>
<!-- 这里表示 //user.do会由 名称为UserController的对应的控制器来apps.hibernatetest.ioc.UserController处理-->
</props>
</property>
</bean>
</beans>
2.hibernate配置文件:
这里主要是映射文件 :User.hbm.xml 与表USER_TABLE 对应
名称为:User.hbm.xml
详细配置代码如下:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="apps.hibernatetest.ioc.User" table="USER_TABLE">
<id name="id" type="string" unsaved-value="null">
<column name="ID" sql-type="varchar2(255)" not-null="true" />
<generator class="uuid.hex"/>
</id>
<property name="username" type="string">
<column name="USERNAME" sql-type="varchar2(20)"/>
</property>
<property name="password" type="string">
<column name="PASSWORD" sql-type="varchar2(20)"/>
</property>
</class>
</hibernate-mapping>
注意:
1.类名一定要写完整路径带包名
2.对应的数据库表明一定要与数据库一致
如: <class name="apps.hibernatetest.ioc.User" table="USER_TABLE">
name属性为:实体类名
table属性为:数据库表的名称
3.其字段信息要与数据库表结构一致
4.该配置文件放在与实体类相同的目录中,并在spring文件中给与说明
如:User.java的完整路径为apps.hibernatetest.ioc.User,对应配置如下
<property name="mappingResources">
<list>
<value>apps/hibernatetest/ioc/User.hbm.xml</value>
</list>
</property>
用hibernate往数据库里插入数据时,出现net.sf.hibernate.MappingException: No persister for的解决办法
根据我的出错处理经验,出现No persister for错误后有如下三种解决办法:
1》检查hbm.xml文件。
2》检查cfg.xml文件,看看类的hbm.xml文件名是不是已经写上了。
3》对于one-to-many(Parent-to-Child)的关系,应该是
child.setParent(parent),而不是child.setParent(parent.id)
3. web.xml文件:
这里对servlet等信息配置:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>ContextLoaderServlet</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 上面定义监听器和上下文装载的servelet,来装载applicatincontext.xml文件 -->
<!-- 下面定义配置Spring的请求分发器类-->
<servlet>
<servlet-name>SpringhibernateStudy</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet>
<servlet-name>debugjsp</servlet-name>
<description>Added to compile JSPs with debug info</description>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>classdebuginfo</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<!-- 下面定义配置Spring的请求分发器将处理所有*.do的请求-->
<servlet-mapping>
<servlet-name>SpringhibernateStudy</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>debugjsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
</web-app>
六、相关各个类的详细代码极其说明
1. User.java 表示用户实体的值对象类,与数据库用户表结构相对应,标准的javabean,提供setter和getter方法。
注意:
1.提供setter和getter方法,符合javabean规范
2.实现java.io.Serializable可序列化接口。
3.与数据库表结构一一对应
User.java
package apps.hibernatetest.ioc;
public class User implements java.io.Serializable
{
private String id;
private String username;
private String password;
public User(){}
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
}
2. UserDAO.java DAO接口
UserDAO.java
package apps.hibernatetest.ioc;
public interface UserDAO
{
public void userAdd(User user);
}
3. UserDAOImp.java DAO接口的实现类
注意:
1. 继承HibernateDaoSupport
2. 实现dao接口
3.使用模板类处理数据
UserDAOImp.java
package apps.hibernatetest.ioc;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Query;
import net.sf.hibernate.Session;
import org.springframework.orm.hibernate.HibernateCallback;
import org.springframework.orm.hibernate.support.HibernateDaoSupport;
public class UserDAOImp extends HibernateDaoSupport implements UserDAO
{
public void userAdd(User user)
{
//try
// {
//System.out.println("save="+getHibernateTemplate().save(user));
System.out.println("aaa====>"+user.getUsername());
System.out.println("bbb====>"+user.getPassword());
getHibernateTemplate().save(user);
System.out.println("bbb");
/* }
catch(Exception e)
{
System.out.println("执行插入用户错误!");
}*/
}
}
4. UserService 业务逻辑层的接口
UserService.java
package apps.hibernatetest.ioc;
public interface UserService
{
public void userAdd(User user);
}
5. UserServiceImp 业务逻辑层的接口的实现类,调用DAO接口实现业务逻辑。
注意:
1.实现指定的service接口
2.接口实现调用DAO接口
3.必须有userDAO属性,并提供setter方法,如下
private UserDAO userDAO;
public UserDAO getUserDAO()
{
return userDAO;
}
public void setUserDAO(UserDAO userDAO)
{
this.userDAO = userDAO;
}
在配置文件中,通过配置自动实现DAO属性的自动注入。
通过这样来定义service业务类和DAO的依赖关系
UserServiceImp.java
package apps.hibernatetest.ioc;
public class UserServiceImp implements UserService
{
private UserDAO userDAO;
private User user = new User();
public UserDAO getUserDAO()
{
return userDAO;
}
public void setUserDAO(UserDAO userDAO)
{
this.userDAO = userDAO;
}
public void userAdd(User user)
{
userDAO.userAdd(user);
}
}
6. UserController web层客户调用层,调用业务逻辑层,实现对业务逻辑的处理。(前台)
UserController.java
package apps.hibernatetest.ioc;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.*;
import javax.servlet.http.*;
import org.springframework.web.bind.RequestUtils;
import java.io.IOException;
import java.util.Map;
import java.util.*;
import java.util.HashMap;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class UserController implements Controller
{
private UserService userService;
public void setUserService(UserService userService)
{
this.userService = userService;
}
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String url="";
url="addok.jsp";
User u=new User();
u.setUsername("aaa");
u.setPassword("bbbb");
userService.userAdd(u);
return new ModelAndView(url);
}
}
注意:
1.实现Controller接口
2.提供私有属性,并提供setter方法
如下代码
private UserService userService;
public void setUserService(UserService userService)
{
this.userService = userService;
}
3.在控制器在handleRequest中调用属性userService调用业务逻辑。
User u=new User();
u.setUsername("aaa");
u.setPassword("bbbb");
userService.userAdd(u);
4. 定义url变量,设置其值,作为ModelAndView类的构造函数的参数,作为业务逻辑处理完后的跳转地址
String url="";
url="addok.jsp";
return new ModelAndView(url);
七,相关项目说明:
调试环境:jbulder9.0
需要导入如下主要的jar包:
spring.jar
hibernate.java
dhcp.java
classes12
等等
八、代码下载:
http://www.e-jrsj.com/hibernatetest.rar
九、在main方法中对在配置文件中的javabean类方法测试的代码:
注意:applicationContext.xml文件放在classes根目录下
package apps.hibernatetest.ioc;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class Test
{
public static void main(String[] args)
{
//根据配置文件得到beanFactory(bean工厂)
Resource resource = new ClassPathResource("applicationContext.xml");
BeanFactory factory = new XmlBeanFactory(resource);
//下面通过bean工厂从配置文件中得到实例化的bean,并转换为相应的接口
UserDAO dao = (UserDAO) factory.getBean("UserDAO");
/*
<bean id="UserDAO" class="apps.hibernatetest.ioc.UserDAOImp">
<property name="hibernateTemplate">
<ref local="hibernateTemplate" />
</property>
</bean>
*/
UserService service = (UserService) factory.getBean("userService");
/*
对应配置文件
<bean id="userService" parent="MyTransactionProxyFactory">
<property name="target">
<bean class="apps.hibernatetest.ioc.UserServiceImp">
<property name="userDAO"><ref local="UserDAO"/></property>
</bean>
</property>
</bean>
*/
System.out.println("tettet");
User u=new User();
u.setUsername("aaa");
u.setPassword("bbbb");
dao.userAdd(u);
service.userAdd(u);
}
}