Cooky - study blog

          Java, Grails, OpenSolaris, Linux, programming, skateboarding...

          Spring + Hibernate 簡單應用

              Spring + Hibernate 是用 POJO 實現JavaEE 輕量級架構在數據持久層和業務層使用的主流模式. POJO 是指 Plain Old Java Object,即"普通Java對象". 輕量級架構可以這樣理解, 它使用了諸如Spring,Hibernate,iBATIS等輕量級框架來開發企業級應用, 相對于傳統的EJB(2.0及以前)重量級架構, 輕量級架構實現更容易,而且"無侵入",或者說沒有侵略性,即使用輕量級框架時非常方便,并可以自由地選擇使用其全部或部分功能,另外也很容易在原有框架的基礎上進行擴展. 關于使用POJO 輕量級架構的詳細信息請參閱<<POJOs IN ACTION>>一書. 此書中文版翻譯得也不錯, 鏈接地址為:
          http://www.china-pub.com/computers/common/info.asp?id=34697.
              這里我舉一個簡單的Spring + Hibernate 的示例, 我是用MyEclipse開發的, 而且使用了Spring對Hibernate封裝后的API來間接操作數據庫.關于Spring 和 Hibernate, 以下兩本書很適合入門時閱讀:
          精通Hibernate:Java對象持久化技術詳解 http://www.china-pub.com/computers/common/info.asp?id=24485(這本書講得不是最新的3.x版本的,但影響不大)
          Spring 2.0核心技術與最佳實踐 http://www.china-pub.com/computers/common/info.asp?id=34820
              由于我使用的是英文版的Eclipse, 我按照做的步驟依序記下了簡單的英文表示,如下所示: (英文可能不太規范,就當偽代碼來讀哈~~ )
          Step in English
          1 New->Web Project:
              Project Name: HSpring
              J2EE Specification Level: Java EE 5.0
          Finish

          2 New->Class:
              Package: test.hspring.model
              Name: User

          3 pragram codes in the class User:
          package test.hspring.model;
          public class User
          {
              private long id;
              private String name;
              private String password;
              private boolean sex;

              public User()
              {
              }
          }

          then press Alt+Shift+S->Generate Getters and Setters...->select all
          then change the "public" modifier of setId(long id) to "private"
          notice that the getter method of boolean-sex filed is isSex() (getSex() is also valid)

          4 right-click on the project HSpring,then select MyEclipse->Add Hibernate Capabilities...
          ensure u select the Hibernate 3.1 Core Libaries and Copy checked Libary Jars to project folder and add to build-path(/WebRoot/WEB-INF/lib)
          then Hibernate config file:New; default settings:src,hibernate.cfg.xml
          Specify database connection details:unchecked(config it later)
          Create sessionFactory class:no

          5 Open the hibernate.cfg.xml file with Configuration View
          check the option Use JDBC Driver
          fill the URL with:   jdbc:mysql://localhost:3306/HSDB
          copy the mysqldriver.jar to WebRoot/WEB-INF/lib
          fill the Driver with: com.mysql.jdbc.Driver(u need first copy the mysql-connector.jar to WebRoot/WEB-INF/lib)
          fill the Username with: root
          fill the Password with ur password, admin eg.
          select Dialect: MySQL

          6 New->XML(Basic Templates) : User.hbm.xml under the package(folder) test.hspring.model,same with User class
          u can find the <!DOCTYPE hibernate-mapping PUBLIC
                "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
          content in the Hibernate3.jar(Referenced Libraries/hibernate3.jar/org.hibernate.hibernate-mapping-3.0.dtd) if u forgot it

          7 edit the file hibernate.cfg.xml, Mappings->Add...->src/test/hspring/model/User.hbm.xml

          8 right-click on the project HSpring,then select MyEclipse->Add Spring Capabilities...
          Spring version: Spring 2
          check MyEclipse Libraries
          select Spring 2.0 AOP Libraries, Spring 2.0 Core Libraries, Spring 2.0 Persistence Core Libraries
          also Copy checked Library contents to project folder..(/WebRoot/WEB-INF/lib)
          check Specify new or existing Spring bean configuration file-> New
          Next
          check Creat Spring LocalSessionFactory that references the hibernate config using a configLocation property: LocalSessionFactory Bean Id: sessionFactory

          9 New->Interface->package: test.hspring.dao   name: UserDAO

          10 New->Class->UserDAOImpl extends HibernateDaoSupport implements UserDAO, package: test.hspring.dao
          notice the methods in this class: this.getHibernateTemplate.get(long id), save(class,long id), update(Object), find(String)...

          11 New->Class->test.hspring.RunThisOnce

          start your MySQL service, open your MySQL client and create a database named HSDB

          right-click in the code of RunThisOnce.java and select Run As->Java Application
          after the class running successfully, delete the "hbm2ddl.auto" property in the filehibernate.cfg.xml
          then you can find the table USERS has been create automantically, and it has a record "cooky"

             
              整個項目工程的下載鏈接為: http://www.aygfsteel.com/Files/cooky/HSpring.rar.
              注意,由于上傳文件大小有限制,我刪除了用到的所有第三方開發包(jar),如果你想直接運行此項目則需先將使用到的jar包copy到HSpring/WebRoot/WEB-INF/lib 文件夾下. 另外你可以跟著我上面的英文步驟和下面的詳細介紹在MyEclipse自動導入包.
              jar包的列表如下,如果提示缺少某些jar,可參考下圖進行導入:



              整個項目工程的包視圖(Package Explorer)如下:



              下面我對前面的英文步驟做一些說明,你可以跟著下面的步驟來做,同時參加前面的英文信息.
              1.新建一個網站項目, 名字為 HSpring, 選擇 Java EE 5.0 版本.

              2.新建一個類User, 作為我們的實體bean(這里是指POJO,不是EJB里的實體bean). 指定包名為 test.hspring.model (此處為方便間接創建包,其實應該先設計包結構再建類)

              3.在User.java 編碼, 先寫四個屬性:id,name,password,sex 和默認構造函數.bean 的定義包含默認構造函數和屬性的getter,setter方法,所以下面添加這四個屬性的訪問方法.直接按快捷鍵Alt+Shift+S 選Generate Getters and Setters...然后選擇全部屬性(為它們生成方法).此快捷鍵建議記住.你也可以右擊代碼然后選擇Source->Generate Getters and Setters....
              另外注意,我們將讓數據庫自動生動主鍵,即以自動增長的方式實現代理主鍵(代理主鍵指主鍵不包含邏輯含義).所以把setId()方法設為private以防止用戶修改id.還有,對于boolean型的屬性如sex, isSex() 和 getSex() 都可以作為此屬性的getter方法.
              User.java 的源代碼如下:
          User.javapackage test.hspring.model;

          /**
           * Model Bean - class
           *
           * @author cooky
           *
           */
          public class User
          {
              private long id;
              private String name;
              private String password;
              private boolean sex;

              /**
               * Default Constructor
               */
              public User()
              {
              }

              public long getId()
              {
                  return id;
              }

              private void setId(long id)
              {
                  this.id = 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;
              }

              /**
               * Return the sex of the user.
               *
               * @return true: female; false: male
               */
              public boolean isSex()
              {
                  return sex;
              }

              /**
               * Set the sex of the user.
               *
               * @return true: female; false: male
               */
              public void setSex(boolean sex)
              {
                  this.sex = sex;
              }
          }

              4.現在我們要加入Hibernate的內容.右擊項目名HSpring,選擇MyEclipse->Add Hibernate Capabilities...,選擇3.1版本的核心包,并選擇"copy checked..."選項以把用到的Hibernate jar包copy到HSpring/WebRoot/WEB-INF/lib文件夾下,這樣你的項目移動時依然可用,不會因為build-path的不一致而需要重新導入包(如果你只是自己演示用,可以選擇只加入build-path).
              下一步中選擇生成新的hibernate.cfg.xml文件,位于src文件夾下.這是使用Hibernate時默認指定的配置文件.然后選擇數據庫連接,如果你已經在MyEclipse配置過你的數據庫(這里我用的是MySQL 5.0),則可以選擇配置好的數據庫連接.否則的話可以取消此項的勾選,稍后在文件中手動配置. 下面一步是問你是否自動生成一個用于訪問Hibernate API的sessionFactory類.由于這里我會用到Spring包裝后的API,所以不選中此項.

              5.第4步中的xml文件生成后,以配置視圖打開該文件(默認情況下已經這樣打開了).現在先在這個文件中配置數據庫連接.選擇使用JDBC驅動,在URL項填jdbc:mysql://localhost:3306/HSDB,當然端口(3306)和數據庫名(HSDB)你可以根據自己的情況自行指定.由于我們后面會在此數據庫中新建USERS表,所以確保現在這個數據庫中沒有此表(不區分大小寫).否則將會覆蓋此表造成數據丟失.(當然你也可以在下面的步驟里重新指定表的名稱而不用USERS,稍后會講到)
              現在要指定數據庫連接用到的驅動類,在這之前,先把MySQL的連接驅動包copy到lib文件夾下(你可以到MySQL官方下載,名稱類似mysql-connector-java-5.0.5-bin.jar).然后指定驅動類為com.mysql.jdbc.Driver. 接著設置用戶名(默認主用戶為root)和密碼(比如我的MySQL訪問密碼是admin).最后選擇數據庫方言為MySQL.
              可能的hibernate.cfg.xml類似:
          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">
          <!-- Generated by MyEclipse Hibernate Tools.                   -->
          <hibernate-configuration>

          <session-factory>
              <property name="connection.url">
                  jdbc:mysql://localhost:3306/HSDB
              </property>
              <property name="myeclipse.connection.profile">
                  JDBC for MySql
              </property>
              <property name="connection.username">root</property>
              <property name="connection.password">admin</property>
              <property name="connection.driver_class">
                  com.mysql.jdbc.Driver
              </property>
              <property name="dialect">
                  org.hibernate.dialect.MySQLDialect
              </property>
              <property name="show_sql">true</property>
              <property name="format_sql">true</property>
              <property name="hbm2ddl.auto">create</propety>
              <mapping resource="test/hspring/model/User.hbm.xml" />
          </session-factory>

          </hibernate-configuration>
              注意,里面最后設置的<mapping />指向第6步中生成的配置文件,此文件用來定義如果把User類映射到數據庫表.另外,我額外添加了三個屬性:show_sql一般在調試時使用,即在控制臺顯示程序執行的sql語句;format_sql用來格式化前面的sql語句,否則每條(比如插入)語句都占一行很不直觀;最后的hbm2ddl.auto屬性設為create,用來配置由數據庫映射文件(如第6步中生成的文件User.hbm.xml)生成數據庫表的定義(ddl),并且執行此ddl(即創建表的sql語句)來自動生成表,這樣就不用手動在數據庫創建表了.由此更可見Hibernate強大的ORM(Object Relational Mapping,對象關系映射)能力.hbm2ddl是基于ant運行的開放工具,由于MyEclipse集成了ant,運用更方便.但使用ant也是J2EE 開發人員必備的能力之一.
              自動生成數據庫表可作為測試用,但我在這里是專門用它來生成表,此表以后就可以使用了,不是為了測試.所以執行一次程序并生成了表后,就要把這個屬性刪除,否則每次執行都會重新建表并覆蓋原來的表了.下面還會詳講.

              6.現在我們就可以新建配置文件,來為User類指定如何映射到數據庫.在test.hspring.model包(或稱文件夾)下新建xml文件User.hbm.xml(你也可以建在其他地方).文件的文件頭<!DOCTYPE>定義了此xml文件的語法,如果你忘記了文件頭的格式,可以去你添加的hibernate3.jar包里找位于最后的兩個dtd文件,分別是cfg.xml和 hbm.xml兩種hibernate配置文件的語法格式,注釋內容中有文件頭示例(或參照下面的代碼).
              User.hbm.xml文件內容如下:
          User.hbm.xml<?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE hibernate-mapping PUBLIC
                "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
          <hibernate-mapping>
              <class name="test.hspring.model.User" table="USERS">
                  <id name="id" column="ID">
                      <generator class="native"></generator>
                  </id>
                  <property name="name" column="NAME" length="20" not-null="true" />
                  <property name="password" column="PASSWORD" length="30"
                      not-null="true" />
                  <property name="sex" column="SEX" />
              </class>
          </hibernate-mapping>
              文件中的一個<class>標簽將對應一個實體bean類,這里只有一個:User. <class>標簽的name屬性指定要映射的實體bean類; table屬性指定要映射的表名,不設置此屬性的話將默認采取類的名稱(如User).類的屬性用<property>子標簽來說明,但用來映射主鍵的屬性(如id)要用用專門的<id>標簽標識.<property>的name屬性和實體bean類里的屬性對應(名稱相同); column屬性指定此屬性將映射到表中的哪一列(字段),不設的話默認和name相同.另外<property>還有not-null,length屬性等,都是故名思義.<id>有個子屬性:<generator>,用來指定主鍵的生成方式,為auto_increment時表示采用Hibernate自己實現的增長機制,為native時表示將采用底層數據庫自己的實現機制,所以移植性更好.關于映射的更多信息請參閱Hibernate的相關內容.
             
              7.現在要把寫好的User.hbm.xml加入hibernate.cfg.xml中.在配置視圖下打開hibernate.cfg.xml,點Mappings區域的Add...,找到User.hbm.xml并選擇.第5步中的hibernate.cfg.xml內容已經實現加入了User.hbm.xml.

              8.Hibernate的配置告一段落,現在來進行和Spring相關的操作.右擊項目名選擇MyEclipse->Add Spring Capabilities...,在出來的對話框中,選擇Spring版本為:Spring 2.0,勾選 MyEclipse Libraries 選項,在列出的jar包里,選擇 Spring 2.0 AOP Libraries, Spring 2.0 Core Libraries, Spring 2.0 Persistence Core Libraries,同樣選中最下面的選項把包copy進項目(或者只加入build-path).然后選擇新建Spring bean 配置文件.下面可以按照默認選項,來生成一個引用已有的Hibernate配置文件的sessionFactory來供Spring使用.

              9.下面我們來實現DAO(Data Access Object,數據訪問對象)的操作.由于Spring鼓勵面向接口編程,所以雖然我們的項目很簡單,還是使用了接口.新建接口(Interface) UserDAO, 位于test.hspring.dao 包下.此接口定義了通過Hibernate訪問數據庫的一系列操作,用來為服務(Service)提供方法,而面向表現層的服務是不能直接調用Hibernate(或Srping)的API來實現這些方法的.以下是其源碼:
          UserDAO.javapackage test.hspring.dao;
          import java.util.List;
          import test.hspring.model.User;
          /**
           * Data Access Object interface
           *
           * @author cooky
           *
           */
          public interface UserDAO
          {
              User getUserByID(long id);
              User getUserByName(String name);
              List<User> listAllUsers();
              void changePassword(User user, String password);
              void addUser(User user);
          }

             
              10.現在編寫實現了以上接口的類(如 UserDAOImpl).在這里我把這個類擴展(繼承)了Spring包里的HibernateDAOSupport類,這樣可以加入Spring提供的事務管理,并通過Spring封裝了Hibernate API后的方法來間接進行數據庫操作(對類的對象進行操作,Hibernate將操作映射到數據庫).這些方法常用的有HibernateTemplate.get(long id), save(class,long id), update(Object), find(String),load()等等.HibernateTemplate對象可由父類中提供的this.getHibernateTemplate()方法得到.以下是UserDAOImpl類的源代碼:
          UserDAOImpl.javapackage test.hspring.dao;
          import java.util.Iterator;
          import java.util.List;
          import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
          import test.hspring.model.User;
          /**
           * An implementation of UserDAO using Spring's API which resue the API of
           * hibernate3
           *
           * @author cooky
           *
           */
          public class UserDAOImpl extends HibernateDaoSupport implements UserDAO
          {
              @Override
              public void addUser(User user)
              {
                  this.getHibernateTemplate().save(user);
              }

              @Override
              public void changePassword(User user, String password)
              {
                  User userToChange = this.getUserByID(user.getId());
                  userToChange.setPassword(password);
                  this.getHibernateTemplate().update(userToChange);
              }

              @Override
              public User getUserByID(long id)
              {
                  User user = (User) this.getHibernateTemplate().get(User.class, id);
                  return user;
              }

              @Override
              public User getUserByName(String name)
              {
                  User user = null;
                  List userList = this.getHibernateTemplate().find("from User u where u.name=?", name);
                  if (!userList.isEmpty())
                  {
                      Iterator userItr = userList.iterator();
                      user = (User) userItr.next();
                  }
                  return user;
              }

              @Override
              public List<User> listAllUsers()
              {
                  List<User> userList = this.getHibernateTemplate().find("from User");
                  if (userList == null || userList.isEmpty())
                  {
                      return null;
                  } else
                  {
                      return userList;
                  }
              }
          }


              11.現在,Hibernate+Spring的內容基本完成,就缺少和表現層交互的內容了.不過,前面提過要運行一次程序以自動生成數據庫表,所以這里我提供了一個類:RunThisOnce,位于test.hspring包.它把一個User對象保存對數據庫.源碼如下:
          RunTestOncepackage test.hspring;
          import org.springframework.context.support.ClassPathXmlApplicationContext;
          import test.hspring.dao.UserDAO;
          import test.hspring.model.User;
          /**
           * Run this class once to generate the tables that to be mapped by hibernate(we
           * only generate one table: USERS). After you run this, delete the
           * "hbm2ddl.auto" property in the file hibernate.cfg.xml
           *
           * @author cooky
           *
           */
          public class RunThisOnce
          {
              public static void main(String[] args)
              {
                  UserDAO userDAO = (UserDAO) new ClassPathXmlApplicationContext("applicationContext.xml").getBean("userDAO");
                  User user = new User();
                  user.setName("cooky");
                  user.setPassword("test-password");
                  user.setSex(false);
                  userDAO.addUser(user);
              }
          }

              在運行之前,要在applicationContext.xml文件中配置要使用的bean: userDAO.這里我們用Spring事務及AOP(Aspect Oriented Programming,面向切面編程)機制來管理bean.配置后的applicationContext.xml內容如下:
          applicationContext.xml<?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
              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-2.0.xsd">
              <bean id="sessionFactory"
                  class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                  <property name="configLocation"
                      value="classpath:hibernate.cfg.xml">
                  </property>
              </bean>

              <bean id="transactionManager"
                  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                  <property name="sessionFactory" ref="sessionFactory"></property>
              </bean>

              <bean id="userDAOTarget" class="test.hspring.dao.UserDAOImpl">
                  <property name="sessionFactory" ref="sessionFactory"></property>
              </bean>

              <bean id="userDAO"
                   class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                  <property name="target" ref="userDAOTarget"></property>
                  <property name="transactionManager" ref="transactionManager"></property>
                  <property name="proxyTargetClass" value="true"></property>
                  <property name="transactionAttributes">
                      <props>
                          <prop key="*">PROPAGATION_REQUIRED</prop>
                      </props>
                  </property>
              </bean>
          </beans>
              bean 的proxyTargetClass屬性設為true,是因為得到bean里可能會拋出ClassCastException,這樣就需要指明此bean為代理bean.其他配置一目了然,userDAO這個代理bean用target屬性指明實際代理的類.關于此處配置的詳細信息(如設置方法中事務的傳播機制等),請參閱Spring 相關內容.
              運行RunThisOnce之前,你還需要開啟MySQL服務,并創建在hibernate.cfg.xml中指定的數據庫(如HSDB).但USERS表不用創建.現在,在RunThisOnce.java的代碼中右擊,選擇 Run As->Java Application, 運行成功后會在數據庫生成USERS表,而且里面有一條記錄(name為"cooky").
              正如前面所說,我運行此程序只為了自動生成數據庫,所以,現在去hibernate.cfg.xml把<property name="hbm2ddl.auto">create</property>刪除,以防止程序每次運行都重新建立表.而且RunThisOnce.java也應該刪除.如果現在再次運行此程序你只會向表中添加name,password和sex都相同的一條新記錄(之前沒有設這三個之中的任一個的unique為true,即允許重復).

              Okay...終于寫完了~~
              那么,表現層(如網頁瀏覽器)怎么和現在的Spring+Hibernate框架進行交互呢(即實現服務/Service)? 你可能想到在Servlet中像RunThisOnce.java中那樣得到applicationContext.xml配置的bean,并調用dao的方法.但是,這樣是極不規范的.Spring配置的bean不能隨便獲取.我會再寫一篇關于JSF與Spring結合的文章來簡單探討這個問題.
              另外,我還會寫一篇關于JUnit單元測試的文章,也會用到現在的這個項目HSpring.



          Keep It Simple, Stupid

          posted on 2007-10-15 23:47 Cooky 閱讀(1752) 評論(12)  編輯  收藏 所屬分類: Java

          評論

          # re: Spring + Hibernate 簡單應用[未登錄] 2007-10-16 11:37 chance

          嚴重頂一下
          我已加入收藏  回復  更多評論   

          # re: Spring + Hibernate 簡單應用 2007-10-17 12:47 Micky

          Hello,Cooky!  回復  更多評論   

          # re: Spring + Hibernate 簡單應用 2007-10-18 00:16 cooky

          @Micky
          Hello u guy  回復  更多評論   

          # re: Spring + Hibernate 簡單應用 2007-10-18 01:59 Micky

          cooky真強~
          鞠躬,握手~
          罪過啊罪過,一開始我還以為這文章是轉載的……  回復  更多評論   

          # re: Spring + Hibernate 簡單應用 2007-10-18 02:03 Micky

          blogjava也挺強,我剛發現原來這里的評論是ajax實現的異步刷新……
          好意外~~
          這么老土古舊的博客模板了。真是模板不可貌相。。。  回復  更多評論   

          # re: Spring + Hibernate 簡單應用 2007-10-19 00:35 cooky

          @Micky
          對你真是無語了...  回復  更多評論   

          # re: Spring + Hibernate 簡單應用 2008-03-23 19:44

          不錯,牛寫得這么清楚  回復  更多評論   

          # re: Spring + Hibernate 簡單應用[未登錄] 2008-04-11 17:54 ling

          正在學,感謝哦,很詳細啊!嘿嘿,樓主以后多發一些哦!  回復  更多評論   

          # re: Spring + Hibernate 簡單應用 2008-11-12 10:26 ddd

          henhao!  回復  更多評論   

          # re: Spring + Hibernate 簡單應用 2008-12-03 13:02 marshall

          試一下AJAX更新..  回復  更多評論   

          # re: Spring + Hibernate 簡單應用 2008-12-03 13:02 marshall

          哈哈,,再來一次,  回復  更多評論   

          # re: Spring + Hibernate 簡單應用 2008-12-23 21:57 xc

          試一下,哈哈  回復  更多評論   

          主站蜘蛛池模板: 贵州省| 康保县| 普兰店市| 鞍山市| 南开区| 宣恩县| 航空| 荃湾区| 基隆市| 宣汉县| 江口县| 云和县| 西青区| 门头沟区| 武定县| 河源市| 怀远县| 军事| 江北区| 宜州市| 莫力| 清流县| 安化县| 平乡县| 溧水县| 水富县| 昆明市| 托克逊县| 襄汾县| 大安市| 土默特右旗| 龙陵县| 治多县| 漾濞| 洛川县| 北海市| 华安县| 乐清市| 克拉玛依市| 玛纳斯县| 内江市|