【JavaEE】Springmvc+Spring+Hibernate整合及example

时间:2022-09-14 09:48:11

前面两篇文章,分别介绍了SpringmvcSpring的搭建方法,本文再搭建hibernate,并建立SSH最基本的代码结构。

Hibernate和前面两个比就比较复杂了,Hibernate是一个orm的框架,也就是负责面向对象中的对象(Object)和关系型数据库这个关系(Relation)之间的映射(Mapping)。因为关系型数据库的思维方式,和编程的时候对于对象的理解是有偏差的,所以也有一些面向对象的数据库,但是随着这些orm框架的完善,面向对象的数据库就销声匿迹了。

当然,我这篇文章也只是搭建环境,并不多讲annotation,这个会专门写一篇来讲。

闲话少说,第一步是安装好数据库,我用的是mysql,安装在本地,本开启了mysql服务。之后看程序怎么改进。

1. pom.xml

第一步加入hibernate的相关jar包,首先在properties标签下面定义一个版本:

<properties>
<spring.version>4.0.4.RELEASE</spring.version>
<hibernate.version>4.3.5.Final</hibernate.version>
</properties>

然后加入hibernate的核心包,因为要让Spring管理一些对象,还要引入spring-orm的包:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>

除此之外,因为我们要用mysql数据库,并使用c3p0连接池,因此需要引入这两个对应的包:

<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.31</version>
</dependency>

2. web.xml

hibernate有两种使用方法,一种是通过一个SessionFactory来获取Session,还有一种是通过EntityManagerFactory来获取entityManager,我忘了什么原因了,刚开始用的EntityManager后来换回了SessionFactory(hibernate3以前用的是SessionFactory),我后面的描述也都是基于sessionFactory了。而不管是Session还是EntityManager,我们都要去创建和管理这个对象,当然,有了Spring,这个事情就不用我们来操心了,只需要在Spring的配置文件里面配置一下我需要的SessionFactory就行了,不过为了每个文件专注一个事情,我又单独配了一个配置文件,而不是用之前Spring的那一个applicationContext.xml,修改之前的contextConfigLocation,加一个新的文件位置:

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/META-INF/applicationContext.xml,
classpath:/META-INF/infrastructure.xml</param-value>
</context-param>

除此之外,hibernate本质上不需要在web.xml里面配置什么,但是有一个属性,我觉得很重要,hibernate对对象的管理是基于session的,如果开启了延迟加载,对于关联对象的查询可能会在渲染jsp的时候才发生,但是这个时候hibernate的当前session默认已经关闭了,就会抛异常,所以我们经常需要hibernate在渲染jsp页面的时候还开着session,这就需要在web.xml中配置一个拦截所有请求的filter:

<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

3. infrastructure.xml

在src/main/resources这个资源包的META-INF目录下创建infrastructure.xml,在这里配置hibernate的SessionFactory:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
"> <context:property-placeholder location="classpath:/META-INF/properties/hibernate.properties" /> <!-- 使用C3P0数据源,MySQL数据库 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<!-- MySQL5 -->
<property name="driverClass" value="${driverClassName}"></property>
<property name="jdbcUrl" value="${url}"></property>
<property name="user" value="${username}"></property>
<property name="password" value="${password}"></property>
<property name="maxPoolSize" value="40"></property>
<property name="minPoolSize" value="1"></property>
<property name="initialPoolSize" value="1"></property>
<property name="maxIdleTime" value="20"></property>
</bean> <!-- session工厂 -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="org.zhangfc.demo4ssh.domain" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
</props>
</property>
</bean> <bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean> <tx:annotation-driven transaction-manager="transactionManager" /> </beans>

首先要主意我标称玫红的部分,这是实体类的存放package,hibernate就是用这下面的实体类和数据表对应,需要修改成自己的package,可以看到这个文件还是比较长,不利于改参数,所以继续抽取一个属性文件出来,property-placeholder就是这个文件的位置,之后配置一个数据源,用c3p0连接池连接数据库,之后再根据这个数据源配置SessionFactory,进而配置事务,配置SessionFactory的时候有一个属性hibernate.hbm2dll.auto,是配置根据我们对类的定义自动生成数据表及主外键关系的,刚创建工程的时候设置成create,以后可以改成update或者删了这个属性(刚建工程的时候就设置成update也可以自己创建数据表,但是不会打印建表的sql语句),下面来看这个抽取出来的属性文件,在同目录下创建子目录properties,再创建hibernate.properties:

hibernate.dialect=org.hibernate.dialect.MySQLDialect
driverClassName=com.mysql.jdbc.Driver
validationQuery=SELECT 1
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
username=root
password= hibernate.hbm2ddl.auto=create
hibernate.show_sql=true
hibernate.format_sql=true

4. applicationContext.xml

还需要改这个文件吗?需要改一点,这个文件之前只有一行:

<context:component-scan base-package="org.zhangfc.demo4ssh.service"/>

SSH最基本的代码结构呢,需要有实体类,也就是持久化对象,这是一些和数据表一一对应的类,这些类我们放在domain这个子package下,然后访问数据库要使用DAO,即数据访问对象,我们为它们创建一个repo包,再加上之前已经有的serivce和controller,基本架子就全了,所以,不光service要交给spring来管理,repo和domain都要让spring来扫描:

<context:component-scan base-package="org.zhangfc.demo4ssh.service"/>
<context:component-scan base-package="org.zhangfc.demo4ssh.domain"/>
<context:component-scan base-package="org.zhangfc.demo4ssh.repo"/>

5. domain.User/repo.UserDao/service.UserService

首先在domain包下创建实体类User,我们就用最简单的只有两个字段,id和username:

@Entity
@Table
public class User implements Serializable {
private static final long serialVersionUID = 172643386440351811L;
private int id;
private String username; @Id
@GeneratedValue
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
}

@Size(min=6)
public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} }

这里的annotation用的都是JPA的接口,所以都是javax.persistence包下的,annotation加在变量上和getter方法上都可以,只不过加在public域更好一些,这儿为User对象定义了两个成员,id是主键、自增长,还有一个username,并对username做了一个限制,比如长度超过6才可以。

之后定义一个dao来访问数据库,创建一个新的package叫做repo(org.zhangfc.demo4ssh.repo),创建UserDao:

public interface UserDao {
public int save(User u);
public List<User> findAll();
}

创建实现类UserDaoImpl:

@Repository
public class UserDaoImpl implements UserDao { @Autowired
private SessionFactory sessionFactory; public List<User> findAll() {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(User.class);
return criteria.list();
} }

首先一个annotation注明这是一个repository,需要被Spring管理,然后自动装载之前在配置文件中配置的SessionFactory,获取当前session后获取所有的用户,下面修改之前的UserService代码,service封装业务逻辑层代码,我把每个service方法封装为一个事务,注:上面的SessionFactory获取当前Session是依赖于事务的,如果不在某个事务之内,会报错:No Session found for current thread。

UserService:

public interface UserService {
public void saveUsers(List<User> us);
public List<User> getAllUsers();
}

UserServiceImpl:

@Service
@Transactional
public class UserServiceImpl implements UserService { @Autowired
private UserDao userDao; public void saveUsers(List<User> us) {
for (User u : us) {
userDao.save(u);
}
} public List<User> getAllUsers() {
return userDao.findAll();
} }

这个Transactional的annotation就是指明每个方法是一个事务。最后修改HomeController:

@RequestMapping("")
public String home(){
List<User> us = new ArrayList<User>();
User u = new User();
u.setUsername("zhangsan");
us.add(u);
u = new User();
u.setUsername("wangwu");
us.add(u);
userService.saveUsers(us);
return "index";
} @RequestMapping("/json")
@ResponseBody
public List<User> json(){
return userService.getAllUsers();
}

之后运行程序,数据库会自动创建user表(注意,hibernate.hbm2dll.auto=create的话,每次运行程序都会删了之前的表重建,设置为update也会自动建表,且如果数据表已存在但和类的设置不同,会更新数据表,把类中声明的新的东西加上,但是数据表里有、类里面没有的不会在现有的数据表中删除),运行起来之后,访问http://localhost:8080/demo4ssh/会向user表中插入两条记录,因为userService的方法设置了事务,如果其中的任意一条sql执行失败,都将回滚,比如把wangwu改成lisi,因为长度不够,所以第二次插入时失败,那么zhangsan也不会被插入到数据表中。之后再访问http://localhost:8080/demo4ssh/json:

[{"id":1,"username":"zhangsan"},{"id":2,"username":"wangwu"}]

到此为止,SSH的基本框架就搭建出来了。源码下载

【JavaEE】Springmvc+Spring+Hibernate整合及example的更多相关文章

  1. SpringMVC&plus;Spring&plus;Hibernate整合开发

    最近突然想认真研究下java web常用框架,虽然现在一直在用,但实现的整体流程不是很了解,就在网上搜索资料,尝试自己搭建,以下是自己的搭建及测试过程. 一.准备工作: 1/安装并配置java运行环境 ...

  2. SpringMVC&plus;Spring&plus;hibernate整合及分页

    1. 新建web project 2. 引入jar, 3. 创建包com.tgb.web.controller, 下面创建包(dao,entity,service, config,spring,hib ...

  3. 3&period;springMVC&plus;spring&plus;Mybatis整合Demo(单表的增删该查,这里主要是贴代码,不多解释了)

    前面给大家讲了整合的思路和整合的过程,在这里就不在提了,直接把springMVC+spring+Mybatis整合的实例代码(单表的增删改查)贴给大家: 首先是目录结构: 仔细看看这个目录结构:我不详 ...

  4. SpringMVC&plus;Spring&plus;Hibernate的小样例

    Strusts2+Spring+Hibernate尽管是主流的WEB开发框架,可是SpringMVC有越来越多的人使用了.确实也很好用.用得爽! 这里实现了一个SpringMVC+Spring+Hib ...

  5. Maven搭建springMVC&plus;spring&plus;hibernate环境

    这次不再使用struts2做控制器,采用spring自己的springMVC框架实现. 首先,改写pom.xml文件,不需要struts2的相关jar了. pom.xml <project xm ...

  6. SpringMVC&plus;Spring&plus;Mybatis整合

    SpringMVC+Spring+Mybatis整合 导包 配置jdbc.properties.log4j.properties jdbc.driver=com.mysql.jdbc.Driver j ...

  7. Struts2&plus;Spring&plus;Hibernate整合开发(Maven多模块搭建)

    Struts2+Spring+Hibernate整合开发(Maven多模块搭建) 0.项目结构 Struts2:web层 Spring:对象的容器 Hibernate:数据库持久化操作 1.父模块导入 ...

  8. Springmvc&plus;Spring&plus;Mybatis整合开发(架构搭建)

    Springmvc+Spring+Mybatis整合开发(架构搭建) 0.项目结构 Springmvc:web层 Spring:对象的容器 Mybatis:数据库持久化操作 1.导入所有需要的jar包 ...

  9. spring&plus;hibernate整合:报错org&period;hibernate&period;HibernateException&colon; No Session found for current thread

    spring+hibernate整合:报错信息如下 org.hibernate.HibernateException: No Session found for current thread at o ...

随机推荐

  1. GsonFormat插件从配置到使用

    说明:目前多数服务器端都以json格式返回,那么相对应的解析时建立的实体类如果你还在自己挨个写的话,那就out了.新建一个类,选择Generate. ------------------------- ...

  2. Linux多线程学习总结

    线程是程序中完成一个独立任务的完整执行序列,即一个可调度的实体:进程相当于运行中程序的一种抽象.根据运行环境的调度者的身份,线程可分为内核线程和用户线程.内核线程,在有的系统上称为LWP(Light ...

  3. MSMQ 学习&lpar;1&rpar;

    在 Windows Server 2008 or Windows Server 2008 R2 上安装消息队列 4.0 在服务器管理器中,单击“功能”. 在“功能摘要”下的右窗格中,单击“添加功能”. ...

  4. Flux Demo解析

    最近学习了阮一峰老师的博文 "Flux入门教程",博文中详细介绍了Flux框架和Controller view模式,并提供了Demo,受益匪浅. 现特参考阮老师的Demo,绘制了一 ...

  5. 解决CI框架的Disallowed Key Characters错误提示

    用CI框架时,有时候会遇到这么一个问题,打开网页,只显示 Disallowed Key Characters 错误提示.有人说 url 里有非法字符.但是确定 url 是纯英文的,问题还是出来了.但清 ...

  6. How Do I Declare A Block in Objective-C&quest;

    As a local variable: returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...}; As a p ...

  7. C&plus;&plus;设计模式——中介者模式

    前言 我们都知道,这个国际政治是一门很深的学问,不玩政治的人是搞不懂的.那么多的国家,国家之间的关系又及其复杂:就好比现在,美国和中国有经济利益关系,美国又和日本有盟友关系,朝鲜又和中国有说不清道不明 ...

  8. springboot打包去除资源文件,启动时指定配置文件位置,使用log4j2替换默认logback

    springboot打包时,去掉资源文件 <build> <resources> <resource> <directory>src/main/reso ...

  9. 函数和常用模块【day06】:random模块(三)

    本节内容 1.简述 2.random模块 3.string模块 4.生成随机数 一.简述 我们经常会使用一些随机数,或者需要写一些随机数的代码,今天我们就来整理随机数模块:random模块 二.ran ...

  10. pytest六:parametrize-参数化

    pytest.mark.parametrize 装饰器可以实现测试用例参数化. 1.这里是一个实现检查一定的输入和期望输出测试功能的典型例子 import pytest @pytest.mark.pa ...