java框架简介1--spring+hibernate简介 2 基本结合

Spring+Hibernate简介:

本文目的是理解Spring的功能。对于一个初学者来说,可能很难理解Spring到底是干什么的,我们为什么要使用Spring,尤其是那些没有学过EJB的同学。本文将会带领您初窥Spring的神秘世界。

 

首先,作为一个大的工程,不能急于忙着一口气把他写完。作为一个有经验的编程人员或者设计师,会将整个复杂的过程分成几步来完成,在保证每一部分无误的情况下,才能使整个工程顺利完成。

本文不但讲解如何将SpringHibernate结合起来,同时也讲解其设计和实现方式。

本文从Hibernate着手,对实体类测试无误后,在进行Spring服务部分的编写,整个工程目录如下:

 

第一部分Hibernate部分的编写与测试:

先要实现model中的类,因为在设计之初就要完成实体模型的抽象和数据库表的建立。Student.java

package com.guan.springHibernateTest.model;

 

import java.util.Date;

 

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

 

@Entity

public class Student {

    private String name;

    private String password;

    private String studentId;

    private Date birthDay;

    private int id;

   

    public String getName() {

       return name;

    }

    public void setName(String name) {

       this.name = name;

    }

    public String getPassword() {

       return password;

    }

    public void setPassword(String password) {

       this.password = password;

    }

    public String getStudentId() {

       return studentId;

    }

    public void setStudentId(String studentId) {

       this.studentId = studentId;

    }

    public Date getBirthDay() {

       return birthDay;

    }

    public void setBirthDay(Date birthDay) {

       this.birthDay = birthDay;

    }

    @GeneratedValue

    @Id

    public int getId() {

       return id;

    }

    public void setId(int id) {

       this.id = id;

    }

}

这个实体类,没有什么可解释的,如果大家不明白,请参考我前面关于Hibernate简介那篇文章。

然后就是Hibernate的配置文件:

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>

 

        <!-- Database connection settings -->

        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>

        <property name="connection.url">jdbc:mysql://localhost/guanxinquan</property>

        <property name="connection.username">root</property>

        <property name="connection.password">gxq</property>

 

        <!-- JDBC connection pool (use the built-in) -->

       

        <!-- SQL dialect -->

        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

   

        <!-- Disable the second-level cache  -->

        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

       <property name="current_session_context_class">thread</property>

        <!-- Echo all executed SQL to stdout -->

        <property name="show_sql">true</property>

       <property name="format_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->

        <property name="hbm2ddl.auto">create</property>

       <mapping class="com.guan.springHibernateTest.model.Student"/>

    </session-factory>

 

</hibernate-configuration>

 

然后需要写一个测试,来测试Hibernate是否正确配置。

StudentModelTest.java

package com.guan.springHibernateTest.model;

 

import java.util.Date;

 

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.AnnotationConfiguration;

import org.junit.AfterClass;

import org.junit.BeforeClass;

import org.junit.Test;

 

public class StudentModelTest {

private static SessionFactory sessionFactory = null;

   

    @BeforeClass

    public static void beforeClass()

    {

       sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();

    }

   

    @Test

    public void createStudentTest()

    {

       Student student = new Student();

       student.setBirthDay(new Date());

       student.setName("张三");

       student.setStudentId("S05080412");

       student.setPassword("zs");

      

       Session session = sessionFactory.openSession();

       session.beginTransaction();

       session.save(student);

       session.getTransaction().commit();

       session.close();

    }

   

    @AfterClass

    public static void afterClass()

    {

       sessionFactory.close();

    }

   

    public static void main(String[] args){

      

       beforeClass();

    }

}

注意,在这个测试中,我们向数据库中添加了一个同学。在后面的Spring的测试中,我们需要获取这个同学的信息。

需要注意的是,model的测试程序与原有model的包目录是相同的,只不过是最外层包不同,这样做在引用具体的对象时,不需要import,就向上面写道的那样,并不需要引入Student类。当然了,这样写的真正目的是一种规范,方便测试和管理,在对编写的每一个类都有这样的一个测试程序,会使得程序更健壮,更测试和排错。

 

如果您对以上的内容不是很清楚,请您查看我的关于Hibernate简介那篇文章,这样您将会对上面的代码更加清晰。

 

第二部分 编写服务。

对于一个完整的服务来说,不可能让用户或客户端直接对自身的数据进行操作,而是由服务对客户端或用户以接口的方式提供相应的功能。在服务端,服务也不是直接访问数据的,因为服务完成的是控制层面的业务逻辑,对于更底层的操作不能在服务程序端实现,这样就抽象出来低一层的数据访问层daoData Access Object)就是数据访问接口。

 

实际上,客户端不能直接操作服务的实现,在一个完整的服务中,需要对服务抽象出接口(本例子并没有抽象这个接口,在后续文档中用到时再解释)。

 

话归正题,前面我们实现了model层的功能,下面需要做的是建立服务的架子,之所以说是架子,是由于这个实现过程并不关心其内部的实现内容是什么,而只关心这些接口和实现间的关系。

 

现在,需要写一个beans.xml这个就是今天的主角了,它是Spring的配置文档。

<?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:context="http://www.springframework.org/schema/context"

       xmlns:tx="http://www.springframework.org/schema/tx"

       xmlns:aop="http://www.springframework.org/schema/aop"

      

       xsi:schemaLocation="http://www.springframework.org/schema/beans

           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

           http://www.springframework.org/schema/aop

           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

           http://www.springframework.org/schema/tx

           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

           http://www.springframework.org/schema/context

           http://www.springframework.org/schema/context/spring-context-2.5.xsd">

                  

    

<!—上面的不解释,每次都这么用就行了,下面这句话告诉Spring要扫描这个包下的所有文件,并解释执行Spring的标记 -->

<context:component-scan base-package="com.guan.springHibernateTest"/>

     <!—创建了一个bean(就是一个实例)这个bean是数据库的配置文件,这里我们不再想把数据库配置文件和Spring的配置文件放在一起了,让其单独成一个文件,为以后更改数据库提供方便 -->

    <bean

       class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

       <property name="locations">

           <value>classpath:database.properties</value>

       </property>

    </bean>

    <!—创建一个数据源,这个数据源将会赋值给SessionFactory,内容不解释了很容易理解,注意${}EL表达式,就是取这个变量的值,这些值在database.properties文件中配置,下面会给出这个文件,一看就明白什么意思了 -->

     <bean id="dataSource" destroy-method="close"

       class="org.apache.commons.dbcp.BasicDataSource">

       <property name="driverClassName"

           value="${jdbc.driverClassName}" />

       <property name="url" value="${jdbc.url}" />

       <property name="username" value="${jdbc.username}" />

       <property name="password" value="${jdbc.password}" />

    </bean>

    <!—创建了一个SessionFactory的工厂实例,并赋值了一定的属性-->

    <bean id="sessionFactory"

       class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

       <property name="dataSource" ref="dataSource" />

       <property name="annotatedClasses">

           <list>

    <!—这里告诉Hibernate需要解析哪些实体类,每添加一个实体类,就在这里添加一个value-->           <value>com.guan.springHibernateTest.model.Student</value>

           </list>

       </property>

       <property name="hibernateProperties">

           <props>

              <prop key="hibernate.dialect">

                  ${jdbc.dialect}

              </prop>

              <prop key="hibernate.show_sql">true</prop>

              <prop key="current_session_context_class">thread</prop>

              <prop key="format_sql">true</prop>

              <prop key="hbm2ddl.auto">create</prop>

           </props>

       </property>

    </bean>   

   

</beans>

 

上面这个beans文件,您也不必太上心,只要能看懂,会修改就行了,实际上也没什么可修改的,唯一值得修改的就是Hibernate中的list,当您增加了实体类,就将这个实体添加到那个位置就可以了。另外component-scan要改成您的包。

给出数据库配置文件 database.properties

jdbc.driverClassName=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://localhost/guanxinquan

jdbc.username=root

jdbc.password=gxq

jdbc.dialect=org.hibernate.dialect.MySQLDialect

 

这个文件,是对数据库的配置,如果您需要修改数据库,代码的其他部分是无需修改的,仅仅是修改这个文件就可以了。

 

下面是服务配置部分,首先需要在impl中添加一个SuperImpl.java实际上不是必须的,我习惯这样写。这样写的好处就是在所有剩下的impl类中都继承这个父类,就省去了引用HibernateSessionFactory的麻烦:

SuperImpl.java

package com.guan.springHibernateTest.impl;

 

import org.hibernate.SessionFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

 

public class SuperImpl extends HibernateDaoSupport{

    @Autowired/*告诉Spring,当创建这个类的实例的时候,要注入一个SessionFactory类型的一个实体,就是说将beans.xml中创建的sessionFactory注入进来,就是把他的引用传进来 如果您对注入的概念不清晰,请参考Spring的官方文档*/

    public void setHibernateSessionFactory(SessionFactory sessionFactory)

    {

       this.setSessionFactory(sessionFactory);

    }

}

注入:就是对象在创建之前确定其依赖的对象,然后由系统将与之相关的对象直接传递给他。如果您还不明白,更白话点说就是相当于您写了一个构造函数,这个构造函数有一些参数,这些参数在对象实例化的时候需要您提供其实例。但是这样理解并是注入的真正含义。

 

下面给出Dao

StudentDao.java

package com.guan.springHibernateTest.dao;

 

import com.guan.springHibernateTest.model.Student;

 

public interface StudentDao {

 

}

 

开始写Dao的时候并不关心内部到底需要提供哪些接口,实际上我们现在只是在搭个架子,然后我们采用用例驱动来完成真个内部功能。

 

然后要写dao的实现:

package com.guan.springHibernateTest.impl;

 

import org.springframework.stereotype.Component;

 

import com.guan.springHibernateTest.dao.StudentDao;

import com.guan.springHibernateTest.model.Student;

 

@Component("studentDao")/*这个标记标示在Spring初始化的时候要创建这样的一个实例,并且这个实例(有人可能叫做对象)的名字叫(studentDao)。实际上在Spring框架中这个实例是一个bean,他很可能注入到其他的实例中*/

/*注意这个实例继承了SuperImpl并且实现了StudentDao(尽管现在还没写但是一会就填上)*/

public class StudentDaoImpl extends SuperImpl implements StudentDao{

}

 

 

然后,将要写一个服务

StudentService.java

package com.guan.springHibernateTest.service;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

 

import com.guan.springHibernateTest.dao.StudentDao;

import com.guan.springHibernateTest.model.Student;

 

@Component("studentService")/*告诉Spring在框架加载的时候要生成一个这个类型并叫做studentService的实例*/

public class StudentService implements StudentDao{

 

    private StudentDao studentDao;//这里定义了一个变量

   

    public StudentDao getStudentDao() {

       return studentDao;

    }

 

    @Autowired/*Spring框架加载时要将StudentDao这个属性注入进来,如果您还没有忘记的话这个StudentDao刚刚在StudentDaoImpl.java中实现的*/

    public void setStudentDao(StudentDao studentDao) {

       this.studentDao = studentDao;

    }

   

}

 

 

最后需要写一个测试程序:

StudentServiceTest.java

package com.guan.springHibernateTest.service;

 

import org.junit.Test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

import com.guan.springHibernateTest.model.Student;

 

 

public class StudentServiceTest {

    @Test

    public void StudentGetTest()

    {

        ApplicationContext appContext = new ClassPathXmlApplicationContext("beans.xml");/*通知Spring要分析beans.xml这个文件,就是告诉Spring它的配置描述文件在哪里*/

 

/*然后获得那个叫studentService的实例,然后我们就会使用这个实例来进行操作*/

        StudentService studentService = (StudentService) appContext.getBean("studentService");

    }

}

可能您看到这里已经是脑中一片混乱了,我简单的解释下Spring的这个流程:首先在测试程序中我们执行了ApplicationContext appContext = new ClassPathXmlApplicationContext("beans.xml");这句,告诉Spring处理beans.xml(实际上用告诉是不合理的,就是调用了Spring)Spring分析xml文档,发现有个SessionFactorybean,就创建了一个叫sessionFactory的对象(我习惯叫实例),然后再xml文档中告诉Spring要扫描com.guan.springHibernateTest 下的所有类<context:component-scan base-package="com.guan.springHibernateTest"/>

这样Spring扫描到SuperImpl实现时需要注入SessionFactory,并且自己现在已经有了这样的实例。然后Spring又发现StudentDaoImpl要求在框架加载时创建他@Component("studentDao"),并且它又继承于SuperImpl,这样Spring创建StudentDaoImpl的实例,并将现在已经创建好的sessionFactory注入给他。当Spring继续扫描,发现studentService在框架加载的时候需要创建它@Component("studentService"),并且需要注入一个StudentDao类型的对象,很明显我们刚刚创建的studentDao正是这个类型(注意studentDaoStudentDaoImpl类型,但是StudentDaoImpl实现了StudentDao接口,所有StudentDaoImpl也是StudentDao类型),于是创建StudentService并将studentDao注入其中。

然后执行测试程序中的第二句:

StudentService studentService = (StudentService) appContext.getBean("studentService");

应用程序要从Spring中获取一个叫studentService的实例,不正是我们上面创建的那个吗,于是Spring就将这个实例反馈给用户实例。

 

如果您还是不明白,你可以和我一起探讨。

 

另外需要明白的是,Spring生成的这些bean一般都是单体类,就是说在整个过程中只有一个类的实例。一般这种单体类是很常见的,对应控制类来说,都应该建立成这种单体类。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值