先決條件 :
為了嘗試以下示例,您將需要以下提到的JAR文件:
- org.springframework.aop-3.0.6.RELEASE.jar
- org.springframework.asm-3.0.6.RELEASE.jar
- org.springframework.aspects-3.0.6.RELEASE.jar
- org.springframework.beans-3.0.6.RELEASE.jar
- org.springframework.context.support-3.0.6.RELEASE.jar
- org.springframework.context-3.0.6.RELEASE.jar
- org.springframework.core-3.0.6.RELEASE.jar
- org.springframework.jdbc-3.0.6.RELEASE.jar
- org.springframework.orm-3.0.6.RELEASE.jar
- org.springframework.transaction-3.0.6.RELEASE.jar。
- org.springframework.expression-3.0.6.RELEASE.jar
- commons-logging-1.0.4.jar
- log4j.jar
- aopalliance-1.0.jar
- dom4j-1.1.jar
- hibernate-commons-annotations-3.2.0.Final.jar
- hibernate-core-3.6.4.Final.jar
- hibernate-jpa-2.0-api-1.0.0.Final.jar
- javax.persistence-2.0.0.jar
- jta-1.1.jar
- javassist-3.1.jar
- slf4j-api-1.6.2.jar
- mysql-connector-java-5.1.13-bin.jar
- commons-collections-3.0.jar
對于希望eclipse項目進行嘗試的任何人,您都可以在此處下載帶有上述JAR依賴項的文件。
簡介 :
成立于2011年。正義聯盟(Justice League)的規模過大,正在尋找開發商來幫助創建超級英雄注冊系統。 熟悉Hibernate和ORM的開發人員已準備好使用Hibernate來完成系統和處理持久層的工作。 為簡單起見,他將使用一個簡單的獨立應用程序來保留超級英雄。 這是此示例的布局方式:
- 桌子設計
- 域類和Hibernate映射
- DAO和服務類
- 應用程序的Spring配置
- 一個簡單的主類,展示所有工作原理
讓旅程開始……………………。
表格設計:
設計由三個簡單的表格組成,如下圖所示;

如您所見,它是一個簡單的一對多關系,由聯接表鏈接。 Hibernate將使用Join Table來填充域類中的Super hero列表,我們將在下一步繼續查看。
域類和Hibernate映射:
與主要擁有實體(正義聯盟實體)鏈接的聯接表主要只有兩個域類。 因此,讓我們繼續看看如何使用注釋構造域類。
package com.justice.league.domain;import java.io.Serializable;import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;import org.hibernate.annotations.Type;@Entity
@Table(name = "SuperHero")
public class SuperHero implements Serializable {/*** */private static final long serialVersionUID = -6712720661371583351L;@Id@GeneratedValue(strategy = GenerationType.AUTO)@Column(name = "super_hero_id")private Long superHeroId;@Column(name = "super_hero_name")private String name;@Column(name = "power_description")private String powerDescription;@Type(type = "yes_no")@Column(name = "isAwesome")private boolean isAwesome;public Long getSuperHeroId() {return superHeroId;}public void setSuperHeroId(Long superHeroId) {this.superHeroId = superHeroId;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPowerDescription() {return powerDescription;}public void setPowerDescription(String powerDescription) {this.powerDescription = powerDescription;}public boolean isAwesome() {return isAwesome;}public void setAwesome(boolean isAwesome) {this.isAwesome = isAwesome;}}
因為我將MySQL用作主要數據庫,所以我將GeneratedValue策略用作GenerationType.AUTO ,只要創建了新的超級英雄,它將自動進行遞增。 所有其他映射都為大家所熟悉,除了
我們將布爾值映射到數據庫中Char字段的最后一個變量。
我們在數據庫字段中使用Hibernate的@Type批注將true&false表示為Y&N。 Hibernate有許多@Type實現,您可以在這里閱讀。 在這種情況下,我們使用了這種類型。
好了,現在我們有了代表超級英雄的班級,讓我們繼續看一下我們的正義聯盟領域的模樣,這將保留所有對聯盟表示忠誠的超級英雄。
package com.justice.league.domain;import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;@Entity
@Table(name = "JusticeLeague")
public class JusticeLeague implements Serializable {/*** */private static final long serialVersionUID = 763500275393020111L;@Id@GeneratedValue(strategy = GenerationType.AUTO)@Column(name = "justice_league_id")private Long justiceLeagueId;@Column(name = "justice_league_moto")private String justiceLeagueMoto;@Column(name = "number_of_members")private Integer numberOfMembers;@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER, orphanRemoval = true)@JoinTable(name = "JUSTICE_LEAGUE_SUPER_HERO", joinColumns = { @JoinColumn(name = "justice_league_id") }, inverseJoinColumns = { @JoinColumn(name = "super_hero_id") })private List<SuperHero> superHeroList = new ArrayList<SuperHero>(0);public Long getJusticeLeagueId() {return justiceLeagueId;}public void setJusticeLeagueId(Long justiceLeagueId) {this.justiceLeagueId = justiceLeagueId;}public String getJusticeLeagueMoto() {return justiceLeagueMoto;}public void setJusticeLeagueMoto(String justiceLeagueMoto) {this.justiceLeagueMoto = justiceLeagueMoto;}public Integer getNumberOfMembers() {return numberOfMembers;}public void setNumberOfMembers(Integer numberOfMembers) {this.numberOfMembers = numberOfMembers;}public List<SuperHero> getSuperHeroList() {return superHeroList;}public void setSuperHeroList(List<SuperHero> superHeroList) {this.superHeroList = superHeroList;}}
這里要注意的重要事實是注釋@OneToMany(cascade = {CascadeType.ALL},fetch = FetchType.EAGER,orphanRemoval = true) 。 在這里,我們設置了orphanRemoval = true 。
那到底是做什么的呢?
好吧,假設您的聯賽中有一群超級英雄。 并說一個超級英雄是干草堆。 所以我們需要從聯盟中移除他/她。 使用JPA級聯,由于無法檢測孤立記錄,因此這是不可能的 然后您將擁有刪除了“超級英雄”的數據庫,而您的收藏中仍然有對它的引用。
在JPA 2.0之前,您沒有orphanRemoval支持,并且是刪除孤立記錄的唯一方法
是要使用以下Hibernate特定(或ORM特定)注釋,現在已棄用 ;
@ org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
但是,通過引入屬性orphanRemoval,我們現在能夠通過JPA處理孤立記錄的刪除。
現在我們有了Domain類
DAO和服務類:
為了保持良好的設計標準,我將DAO(數據訪問對象)層和服務層分開。 因此,讓我們看一下DAO的界面和實現。 請注意,我有
通過HibernateDAOSupport使用了HibernateTemplate ,從而避免了任何特定于Hibernate的細節,并使用Spring以統一的方式訪問所有內容。
package com.justice.league.dao;import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;import com.justice.league.domain.JusticeLeague;@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public interface JusticeLeagueDAO {public void createOrUpdateJuticeLeagure(JusticeLeague league);public JusticeLeague retrieveJusticeLeagueById(Long id);
}
在接口層中,我已根據需要定義了事務處理。 這樣做是為了使每當不需要事務時,您都可以在該特定方法的方法級別定義它,在更多情況下,您將需要事務
除了數據檢索方法。 ?
根據JPA規范,您需要一個有效的事務來執行插入/刪除/更新功能 。
因此,讓我們看一下DAO的實現;
package com.justice.league.dao.hibernate;import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;import com.justice.league.dao.JusticeLeagueDAO;
import com.justice.league.domain.JusticeLeague;@Qualifier(value="justiceLeagueHibernateDAO")
public class JusticeLeagueHibernateDAOImpl extends HibernateDaoSupportimplements JusticeLeagueDAO {@Overridepublic void createOrUpdateJuticeLeagure(JusticeLeague league) {if (league.getJusticeLeagueId() == null) {getHibernateTemplate().persist(league);} else {getHibernateTemplate().update(league);}}@Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = false) public JusticeLeague retrieveJusticeLeagueById(Long id){return getHibernateTemplate().get(JusticeLeague.class, id);}}
在這里,我定義了一個@Qualifier,以讓Spring知道這是DAO類的Hibernate實現。 請注意以休眠結尾的軟件包名稱。 在我看來,這是一個很好的設計概念,可遵循的將您的實現分離為
分開包裝以保持設計整潔。
好的,讓我們繼續進行服務層的實現。 在這種情況下,服務層只是充當調用DAO方法的中介層。 但是在現實世界的應用程序中,您可能會在服務層中進行其他驗證,與安全性相關的過程等。
package com.justice.league.service;import com.justice.league.domain.JusticeLeague;public interface JusticeLeagureService {public void handleJusticeLeagureCreateUpdate(JusticeLeague justiceLeague);public JusticeLeague retrieveJusticeLeagueById(Long id);
}
package com.justice.league.service.impl;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;import com.justice.league.dao.JusticeLeagueDAO;
import com.justice.league.domain.JusticeLeague;
import com.justice.league.service.JusticeLeagureService;@Component("justiceLeagueService")
public class JusticeLeagureServiceImpl implements JusticeLeagureService {@Autowired@Qualifier(value = "justiceLeagueHibernateDAO")private JusticeLeagueDAO justiceLeagueDAO;@Overridepublic void handleJusticeLeagureCreateUpdate(JusticeLeague justiceLeague) {justiceLeagueDAO.createOrUpdateJuticeLeagure(justiceLeague);}public JusticeLeague retrieveJusticeLeagueById(Long id){return justiceLeagueDAO.retrieveJusticeLeagueById(id);}
}
這里沒有什么要注意的。 首先,@ Component在春天上下文中將此服務實現與名稱JusticeLeagueService綁定在一起,以便我們可以將bean稱為ID為JusticeLeagueService的bean 。
并且我們已經自動連接了JusticeLeagueDAO并定義了一個@Qualifier,以便它將綁定到Hibernate實現。
Qualifier的值應與我們在DAO Implementation類中為類級別Qualifier賦予的名稱相同。
最后,讓我們看一下將所有這些連接在一起的Spring配置。
應用程序的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:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"><context:component-scan base-package="com.justice.league" /><context:annotation-config /><tx:annotation-driven /><bean id="sessionFactory"class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"><property name="packagesToScan"><list><value>com.justice.league.**.*</value></list></property><property name="hibernateProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop><prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop><prop key="hibernate.connection.url">jdbc:mysql://localhost:3306/my_test</prop><prop key="hibernate.connection.username">root</prop><prop key="hibernate.connection.password">password</prop><prop key="hibernate.show_sql">true</prop><prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop></props></property></bean><bean id="justiceLeageDAO"class="com.justice.league.dao.hibernate.JusticeLeagueHibernateDAOImpl"><property name="sessionFactory" ref="sessionFactory" /></bean><bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory" /></bean></beans>
請注意,在我單獨運行它的情況下,我在此實例中使用了HibernateTransactionManager 。 如果你是
在應用服務器中運行它,您幾乎總是會使用JTA事務管理器。
為了簡化起見,我還使用了由hibernate自動創建表的方法。 packagesToScan屬性指示掃描根包com.justice.league。**。*下的所有子包(包括嵌套在其中的嵌套包)為
掃描@Entity注釋的類。
我們還將會話工廠限制在了JusticeLeagueDAO上,以便我們可以使用Hibernate Template。
為了進行測試,您可以根據需要最初使用標簽<prop key =“ hibernate.hbm2ddl.auto”> create </ prop> ,然后讓hibernate為您創建表。
好了,現在我們已經看到了應用程序的構建塊,讓我們首先在正義聯盟內創建一些超級英雄,看看它們如何工作
一個簡單的主類來展示所有工作原理:
作為第一個示例,讓我們看看我們將如何通過幾個超級英雄來維持正義聯盟。
package com.test;import java.util.ArrayList;
import java.util.List;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.justice.league.domain.JusticeLeague;
import com.justice.league.domain.SuperHero;
import com.justice.league.service.JusticeLeagureService;public class TestSpring {/*** @param args*/public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-context.xml");JusticeLeagureService service = (JusticeLeagureService) ctx.getBean("justiceLeagueService");JusticeLeague league = new JusticeLeague();List<SuperHero> superHeroList = getSuperHeroList();league.setSuperHeroList(superHeroList);league.setJusticeLeagueMoto("Guardians of the Galaxy");league.setNumberOfMembers(superHeroList.size());service.handleJusticeLeagureCreateUpdate(league);}private static List<SuperHero> getSuperHeroList() {List<SuperHero> superHeroList = new ArrayList<SuperHero>();SuperHero superMan = new SuperHero();superMan.setAwesome(true);superMan.setName("Clark Kent");superMan.setPowerDescription("Faster than a speeding bullet");superHeroList.add(superMan);SuperHero batMan = new SuperHero();batMan.setAwesome(true);batMan.setName("Bruce Wayne");batMan.setPowerDescription("I just have some cool gadgets");superHeroList.add(batMan);return superHeroList;}}
如果我們進入數據庫并進行檢查,我們將看到以下輸出;
mysql> select * from superhero;
+---------------+-----------+-----------------+-------------------------------+
| super_hero_id | isAwesome | super_hero_name | power_description |
+---------------+-----------+-----------------+-------------------------------+
| 1 | Y | Clark Kent | Faster than a speeding bullet |
| 2 | Y | Bruce Wayne | I just have some cool gadgets |
+---------------+-----------+-----------------+-------------------------------+mysql> select * from justiceleague;
+-------------------+-------------------------+-------------------+
| justice_league_id | justice_league_moto | number_of_members |
+-------------------+-------------------------+-------------------+
| 1 | Guardians of the Galaxy | 2 |
+-------------------+-------------------------+-------------------+
如您所見,我們堅持了兩位超級英雄,并將他們與正義聯盟聯系在一起。 現在,讓我們看看下面的示例如何刪除孤兒。
package com.test;import java.util.ArrayList;
import java.util.List;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.justice.league.domain.JusticeLeague;
import com.justice.league.domain.SuperHero;
import com.justice.league.service.JusticeLeagureService;public class TestSpring {/*** @param args*/public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-context.xml");JusticeLeagureService service = (JusticeLeagureService) ctx.getBean("justiceLeagueService");JusticeLeague league = service.retrieveJusticeLeagueById(1l);List<SuperHero> superHeroList = league.getSuperHeroList();/*** Here we remove Batman(a.k.a Bruce Wayne) out of the Justice League* cos he aint cool no more*/for (int i = 0; i < superHeroList.size(); i++) {SuperHero superHero = superHeroList.get(i);if (superHero.getName().equalsIgnoreCase("Bruce Wayne")) {superHeroList.remove(i);break;}}service.handleJusticeLeagureCreateUpdate(league);}}
在這里,我們首先通過主鍵檢索正義聯盟的記錄。 然后,我們循環瀏覽并從聯盟中刪除蝙蝠俠,然后再次調用createOrUpdate方法。 當我們定義了刪除孤兒時,所有不在數據庫列表中的超級英雄都將被刪除。
再次,如果查詢數據庫,我們將看到蝙蝠俠已經按照以下說明被刪除了;
mysql> select * from superhero;
+---------------+-----------+-----------------+-------------------------------+
| super_hero_id | isAwesome | super_hero_name | power_description |
+---------------+-----------+-----------------+-------------------------------+
| 1 | Y | Clark Kent | Faster than a speeding bullet |
+---------------+-----------+-----------------+-------------------------------+
就是這樣了。 正義聯盟(Justice League)如何使用休眠模式自動刪除蝙蝠俠而無需費心自己做的故事。
接下來,我們將期待美國隊長如何使用休眠標準來構建靈活的查詢,以便找到可能的敵人。 小心!!!!
祝大家有美好的一天,并感謝您的閱讀!
如果您有任何建議或意見,請不要理會。
參考:“ 通過示例進行休眠–第1部分(除去孤兒)”,來自我們的JCG合作伙伴 Dinuka Arseculeratne,在“ My Journey Through IT”博客中
- 休眠陷阱
- 休眠自動提交命令強制MySQL在過多的磁盤I / O中運行
- DataNucleus 3.0與Hibernate 3.5
- Hibernate映射集合性能問題
- Spring MVC3 Hibernate CRUD示例應用程序
- Java教程和Android教程列表
翻譯自: https://www.javacodegeeks.com/2011/11/hibernate-by-example-part-1-orphan.html