Статьи

Спящий режим на примере — часть 2 (DetachedCriteria)

Поэтому в прошлый раз мы выручили Лигу Справедливости, чтобы эффективно управлять своими супер героями. Сегодня мы сосредоточимся на том, как Мстители будут использовать Отдельные Критерии Hibernate, чтобы узнать своих врагов по отношению к каждому супергерою, чтобы защитить своих супергероев.

Вы можете скачать рабочий пример отсюда .

В этом примере мы принимаем во внимание только две сущности. Мститель и Злодей. Мы строим отношения между ними, используя таблицу соединений. Давайте посмотрим на сопоставления доменов, используемые в этом примере.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
package com.avengers.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;
  
import org.hibernate.annotations.Type;
  
/**
 * The domain class representing each member of the avengers
 *
 * @author Dinuka.Arseculeratne
 *
 */
@Entity
@Table(name = "Avengers")
public class Avenger implements Serializable {
  
 /**
  * The primary key of the Avenger table
  */
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "avenger_id")
 private Long avengerId;
  
 /**
  * The name of the avenger member
  */
 @Column(name = "avenger_name")
 private String avengerName;
  
 /**
  * A flag which holds whether the avenger's powers are awesome
  */
 @Type(type = "yes_no")
 @Column(name = "is_awesome")
 private boolean isAwesome;
  
 /**
  * The list of enemies the avenger has
  */
 @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
 @JoinTable(name = "AVENGERS_AND_VILLAINS", joinColumns = { @JoinColumn(name = "avenger_id") }, inverseJoinColumns = { @JoinColumn(name = "villain_id") })
 private List<Villain> enemyList = new ArrayList<Villain>();
  
 public Long getAvengerId() {
  return avengerId;
 }
  
 public void setAvengerId(Long avengerId) {
  this.avengerId = avengerId;
 }
  
 public String getAvengerName() {
  return avengerName;
 }
  
 public void setAvengerName(String avengerName) {
  this.avengerName = avengerName;
 }
  
 public boolean isAwesome() {
  return isAwesome;
 }
  
 public void setAwesome(boolean isAwesome) {
  this.isAwesome = isAwesome;
 }
  
 public List<Villain> getEnemyList() {
  return enemyList;
 }
  
 public void addEnemy(Villain enemy) {
  enemyList.add(enemy);
 }
  
 @Override
 public String toString() {
  return "Avenger [avengerId=" + avengerId + ", avengerName="
    + avengerName + ", isAwesome=" + isAwesome + ", enemyList="
    + enemyList + "]";
 }
  
  
}

Этот класс наносит на карту мстителя. Я использовал минимальные поля, чтобы сделать этот пример максимально простым и коротким. И домен злодея выглядит следующим образом;

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package com.avengers.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;
  
/**
 * This class represents the Villain forces against the avengers
 *
 * @author Dinuka.Arseculeratne
 *
 */
@Entity
@Table(name = "Villains")
public class Villain implements Serializable {
  
 /**
  * The primary key of the Enemy table
  */
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "villain_id")
 private Long villaiId;
  
 /**
  * The name of the enemy
  */
 @Column(name = "villain_name")
 private String villainName;
  
 /**
  * A flag which checks whether the villain is super awesome
  */
 @Type(type = "yes_no")
 @Column(name = "is_awesome")
 private boolean isAwesome;
  
 public Long getVillaidId() {
  return villaiId;
 }
  
 public void setVillaidId(Long villaidId) {
  this.villaiId = villaidId;
 }
  
 public String getVillainName() {
  return villainName;
 }
  
 public void setVillainName(String villainName) {
  this.villainName = villainName;
 }
  
 public boolean isAwesome() {
  return isAwesome;
 }
  
 public void setAwesome(boolean isAwesome) {
  this.isAwesome = isAwesome;
 }
  
 @Override
 public String toString() {
  return "Villain [villaiId=" + villaiId + ", villainName=" + villainName
    + ", isAwesome=" + isAwesome + "]";
 }
  
}

Хорошо, теперь, когда мы определили наши домены, давайте посмотрим, как происходит извлечение данных с DetachedCriteria . Я использовал DetachedCriteria здесь, потому что Мстители были очень конкретными и сказали, что они не хотят иметь ничего общего с сеансом Hibernate , поэтому я использовал DetachedCriteria, который не требует присутствия сеанса Hibernate.

Наша главная цель — найти Мстителя, которому принадлежит злодей. Обратите внимание, что это предполагает, что один и тот же злодей не может быть злодеем для нескольких супергероев. Итак, двигаясь дальше, я приведу ниже метод, который извлекает мстителя, основываясь на переданном имени злодея.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public Avenger retrieveAvengerByVillainName(String villainName) {
  
  Avenger avenger = null;
  /**
   * Selected a detached criteria so we do not need a session to run it
   * within.
   */
  DetachedCriteria criteria = DetachedCriteria.forClass(Avenger.class);
  
  /**
   * Here we are doing an inner join with the Villain table in order to do
   * a name comparison with the villainName passed in as a method
   * parameter
   */
  DetachedCriteria villainCriteria = criteria.createCriteria("enemyList");
  
  villainCriteria.add(Restrictions.eq("villainName", villainName));
  
  villainCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
  
  @SuppressWarnings("unchecked")
  List<Avenger> avengerList = getHibernateTemplate().findByCriteria(
    criteria);
  
  if (!avengerList.isEmpty()) {
   avenger = avengerList.get(0);
   getHibernateTemplate().initialize(avenger.getEnemyList());
  }
  return avenger;
  
 }

В этом методе мы сначала создаем критерии для нашего мастер-класса, в данном случае Avenger.class . Затем нам нужно выполнить соединение с таблицей злодеев, и, следовательно, мы создадим подкритерии из наших основных критериев с именем списка, который мы определили в классе домена Avenger.

Тогда нужно сравнить свойство домена Злодея с передаваемым именем злодея.

Сила API Criteria заключается в том, что вы можете легко создавать динамические запросы, что было бы хлопотно, если бы мы использовали чистый HQL, который потребовал бы существенных конкатенаций строк для достижения того же самого.

Пример тестового класса под названием AvengerTest.java приведен с вложением, которое вы можете найти в верхней части. Обратите внимание, что вам нужно удалить комментарий к avenger-context.xml, чтобы создать таблицы, необходимые для этого примера.

Вот и все.

Теперь Мстители могут избежать риска, поскольку у них есть система, с помощью которой они могут связать любого суперзлодея с супергероем в своей лиге.

Как всегда ваши комментарии и предложения всегда приветствуются и ценятся.

Спасибо, что нашли время, чтобы прочитать !!!!

Ссылка: Hibernate на примере — часть 2 (DetachedCriteria) от нашего партнера по JCG Динуки Арурилератне в блоге « Мой путь через ИТ»

Статьи по Теме :