Jarosław Kijanowski
Drools spotyka Hibernate
Streszczenie:
Drools używa faktów umieszczonych w pamięci roboczej. A czy mógłby również "odpytywać" relacyjną bazę danych? Ponieważ możliwość ta otworzyłaby przed Drools całkowicie nową "przestrzeń" zastosowań, a ponadto takie pytanie pojawia się często na listach dyskusyjnych, toteż warto znać odpowiedź, która brzmi: "Oczywiście że tak!"
Hibernate, jedno z najbardziej popularnych narzędzi ORM, pozwala na prosty sposób zarządzania danymi znajdującymi się w relacyjnej bazie danych. Arykuł przedstawi sposób dostępu do obiektu sesji Hibernate z poziomu reguł. Za relacyjną bazę danych posłuży PostreSQL. Modelowana rzeczywistość składa się z dwóch klas, gry oraz gracza, które łączy związek wiele-do-wielu.
- Tworzymy nowy projekt Drools
Nie masz jeszcze zainsatlowanej wtyczki Drools 4.0.7 Eclipse Workbench? Zajrzyj do artykułu pod tytułem "Diabeł tkwi w regułach".
- Klasy
- Hibernate
-
hibernate-3.2.6.GA/lib/antlr-2.7.6.jar
-
hibernate-3.2.6.GA/lib/asm.jar
-
hibernate-3.2.6.GA/lib/cglib-2.1.3.jar
-
hibernate-3.2.6.GA/lib/commons-collections-2.1.1.jar
-
hibernate-3.2.6.GA/lib/commons-logging-1.0.4.jar
-
hibernate-3.2.6.GA/lib/dom4j-1.6.1.jar
-
hibernate-3.2.6.GA/hibernate3.jar
-
hibernate-3.2.6.GA/lib/jta.jar
- Drools
- Jak to działa?
-
możliwość zwracania wyników z powrotem do aplikacji
-
dostęp do serwisów, takich jak sesji Hibernate, JMS czy też innych usług, np. wysyłających wiadomości e-mail, zapisujących dane do pliku, itp.
- Efekt końcowy
- Podsumowanie
Menu File -> New -> Project -> Drools - > Rule Project -> Next. Podajemy nazwę projektu drools-hibernate-demo i wybieramy Next, aby odznaczyć przykładowe pliki
W katalogu src/main/java tworzymy package "eu.kijanowski.drools.hibernate". Będziemy używać dwóch klas, gracza (Player.java) oraz grę (Game.java). Łączy je związek wiele-do-wilu gdyż jeden gracz może posiadać wiele gier, a jedna gra może być własnością wielu graczy ;)
Klasa Game.java
package eu.kijanowski.drools.hibernate;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
public class Game implements Serializable {
private static final long serialVersionUID = 1L;
private Long id = null;
private String name;
private double price;
private int levels;
private Set<Player> players = new HashSet<Player>();
public Game() {
}
public Game(String name, double price, int levels) {
this.name = name;
this.price = price;
this.levels = levels;
}
public Long getId() {
return id;
}
@SuppressWarnings("unused")
private void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getLevels() {
return levels;
}
public void setLevels(int levels) {
this.levels = levels;
}
public Set<Player> getPlayers() {
return players;
}
public void setPlayers(Set<Player> players) {
this.players = players;
}
public String toString() {
return name + " with " + levels + " levels for " + price;
}
}
Klasa Player.java
package eu.kijanowski.drools.hibernate;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
public class Player implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private int age;
private Set<Game> games = new HashSet<Game>();
public Player() {
}
public Player(String name, int age, HashSet<Game> games) {
this.name = name;
this.age = age;
this.games = games;
}
public Long getId() {
return id;
}
@SuppressWarnings("unused")
private void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Set<Game> getGames() {
return games;
}
public void setGames(Set<Game> games) {
this.games = games;
}
public String toString() {
return name;
}
}
Bez szczegółów, innym razem. Pobieramy binaria Hibernate Core 3.2.6 i rozpakowujemy je.
W projekcie tworzymy katalog lib i umieszczamy w nim następujące pliki:
Następnie dodajemy powyższe biblioteki do "build path": z menu Project -> Properties -> Java Build Path -> Libraries wybieramy Add External JARs i wskazujemy na katalog lib naszego projektu. Zaznaczamy wszystkie pliki i zatwierdzamy.
Konfigurujemy Hibernate'a, w katalogu src/main/java tworzymy plik 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>
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="connection.url">jdbc:postgresql://localhost/droolsdb</property>
<property name="connection.username">droolsuser</property>
<property name="connection.password"></property>
<property name="connection.pool_size">1</property>
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<property name="current_session_context_class">thread</property>
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">create</property>
<mapping resource="eu/kijanowski/drools/hibernate/model.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Będziemy używali org.postgresql.Driver, zatem należy dodać bibliotekę do katalogu lib. Ze strony domowej dostawcy bazy PostgreSQL można pobrać odpowiednie sterowniki, ja użyłem 8.2-508 JDBC 3. Następnie należy ją dodać do Java Build Path, tak jak w przypadku bibliotek hibernate'a.
Najwyższy czas pobrać i uruchomić bazę danych PostgreSQL, założyć użytkownika i bazę.
/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data
>logfile 2>&1 &
/usr/local/pgsql/bin/createuser -h 127.0.0.1 -p 5432 -U postgres -s -d
-R droolsuser
/usr/local/pgsql/bin/createdb -h 127.0.0.1 -p 5432 -U postgres -O
droolsuser droolsdb
Ostatni krok, to mapowanie, czyli powiązanie świata obiektowego z światem relacji (tabeli). Tworzymy zatem plik model.hbm.xml w pakiecie eu.kijanowski.drools.hibernate:
<?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 package="eu.kijanowski.drools.hibernate">
<class name="Player" table="PLAYERS">
<id name="id" column="PLAYER_ID" type="java.lang.Long">
<generator class="sequence">
<param name="sequence">player_id_seq</param>
</generator>
</id>
<property name="name" column="NAME" length="10" not-null="true"
type="java.lang.String" />
<property name="age" column="AGE" not-null="true"
type="java.lang.Integer" />
<set name="games" table="PLAYERS_GAMES" cascade="persist, delete, merge, save-update">
<key column="PLAYER_ID" />
<many-to-many column="GAME_ID" class="Game" />
</set>
</class>
<class name="Game" table="GAMES">
<id name="id" column="GAME_ID" type="java.lang.Long">
<generator class="sequence">
<param name="sequence">game_id_seq</param>
</generator>
</id>
<property name="name" column="NAME" length="10" not-null="true"
type="java.lang.String" />
<property name="price" column="PRICE" not-null="true"
type="java.lang.Double" />
<property name="levels" column="LEVELS" not-null="true"
type="java.lang.Integer" />
<set name="players" table="PLAYERS_GAMES">
<key column="GAME_ID" />
<many-to-many column="PLAYER_ID" class="Player"/>
</set>
</class>
</hibernate-mapping>
Pozostało już tylko napisać plik reguł oraz klasę uruchamiającą. W jaki sposób będdzie wykorzystywany Hibernate w naszej aplikacji? Otóż w klasie testującej stworzymy sesję Hibernate i przekażemy ją do pamięci roboczej w postaci stałej globalnej. Wówczas będziemy mieli dostęp do sesji z poziomu reguł. Następnie sformuujemy zapytanie, którego wynik będziemy przeglądać przy użyciu konstrukcji "from". Zatem do dzieła:
Klasa DroolsHibernateTest.java
package eu.kijanowski.drools.hibernate;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
import org.drools.WorkingMemory;
import org.drools.compiler.PackageBuilder;
import org.drools.rule.Package;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class DroolsHibernateTest {
private final static SessionFactory factory;
static {
Configuration cfg = new Configuration().configure();
factory = cfg.buildSessionFactory();
}
public static final void main(String[] args) {
try {
Game g1 = new Game("BF2", 39.99, 5);
Game g2 = new Game("AoE3", 129.99, 45);
Game g3 = new Game("BF3", 139.99, 15);
HashSet<Game> games1 = new HashSet<Game>();
games1.add(g1);
games1.add(g2);
games1.add(g3);
HashSet<Game> games2 = new HashSet<Game>();
games2.add(g1);
games2.add(g3);
Player p1 = new Player("jarek", 26, games1);
Player p2 = new Player("ewelina", 25, games2);
System.out.println(p1.getGames());
System.out.println(p2.getGames());
/* open a Hibernate session and persist data */
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
session.save(p1);
session.save(p2);
tx.commit();
session.close();
/* Let's verify the persisted data */
session = factory.openSession();
tx = session.beginTransaction();
List<Player> players = session.createCriteria(Player.class).list();
System.out.println(players.size() + " player(s) found:");
for (Iterator<Player> iter = players.iterator(); iter.hasNext();) {
Player player = (Player) iter.next();
System.out.println(player.getName() + " has following games: "
+ player.getGames());
}
tx.commit();
session.close();
// load up the rulebase
RuleBase ruleBase = readRule();
WorkingMemory workingMemory = ruleBase.newStatefulSession();
/* pass a hibernate session to the working memory as a global */
session = factory.openSession();
workingMemory.setGlobal("hibernateSession", session);
workingMemory.fireAllRules();
session.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
private static RuleBase readRule() throws Exception {
// read in the source
Reader source = new InputStreamReader(DroolsHibernateTest.class
.getResourceAsStream("/Demo.drl"));
PackageBuilder builder = new PackageBuilder();
// this will parse and compile in one step
builder.addPackageFromDrl(source);
// get the compiled package (which is serializable)
Package pkg = builder.getPackage();
// add the package to a rulebase (deploy the rule package).
RuleBase ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage(pkg);
return ruleBase;
}
}
Plik reguł tworzymy za pomocą wtyczki. Wybieramy katalog src/main/rules i z menu File -> New -> Other... klikamy na Drools -> Rule Resource:
Demo.drl
package eu.kijanowski.drools.hibernate
global org.hibernate.Session hibernateSession;
rule "hibernate_from"
when
game:Game() from hibernateSession.createQuery("select games from Player p where p.age >= :age").setProperties( {"age" : 18 }).list()
then
System.out.println("The game "+game.getName() +"is owned by "+game.getPlayers());
end
Zwróćmy uwagę w pliku reguł na słowo kluczowe global. Za jego pomocą udostępniamy silnikowi reguł zmienne lub stałe z aplikacji. Przy ich użyciu dostajemy:
Należy pamiętać, że zmienne i stałe typu global nie należy zmieniać z poziomu reguł, jeśli używamy ich w części warunkowej reguły (LHS). Ponadto nie służą one do dzielenia informacji pomiędzy regułami. W tym celu należy korzystać z obiektów znajdujących się w pamięci roboczej.
Element warunkowy from z kolei pozwala na przeszukiwanie innych źródeł, niż pamięć roboczą. Należą do nich kolekcje (Collection), mapy (Map) a także wyniki wywołań metod. W naszym przypadku sformuowaliśmy zapytanie do bazy danych i otrzymaliśmy listę gier. Po więcej szczegółów na ten temat odsyłam do dokumentacji Drools
Po uruchomieniu aplikacji (Run as -> Java Application) na ekranie pojawi się
Jun 14, 2008 8:58:11 AM org.hibernate.cfg.Environment <clinit>
INFO: Hibernate 3.2.6
Jun 14, 2008 8:58:11 AM org.hibernate.cfg.Environment <clinit>
INFO: hibernate.properties not found
Jun 14, 2008 8:58:11 AM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: Bytecode provider name : cglib
Jun 14, 2008 8:58:11 AM org.hibernate.cfg.Environment <clinit>
INFO: using JDK 1.4 java.sql.Timestamp handling
Jun 14, 2008 8:58:11 AM org.hibernate.cfg.Configuration configure
INFO: configuring from resource: /hibernate.cfg.xml
Jun 14, 2008 8:58:11 AM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: Configuration resource: /hibernate.cfg.xml
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.Configuration addResource
INFO: Reading mappings from resource : eu/kijanowski/drools/hibernate/model.hbm.xml
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: eu.kijanowski.drools.hibernate.Player -> PLAYERS
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.HbmBinder bindCollection
INFO: Mapping collection: eu.kijanowski.drools.hibernate.Player.games -> PLAYERS_GAMES
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: eu.kijanowski.drools.hibernate.Game -> GAMES
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.HbmBinder bindCollection
INFO: Mapping collection: eu.kijanowski.drools.hibernate.Game.players -> PLAYERS_GAMES
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.Configuration doConfigure
INFO: Configured SessionFactory: null
Jun 14, 2008 8:58:12 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Using Hibernate built-in connection pool (not for production use!)
Jun 14, 2008 8:58:12 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Hibernate connection pool size: 1
Jun 14, 2008 8:58:12 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: autocommit mode: false
Jun 14, 2008 8:58:12 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: using driver: org.postgresql.Driver at URL: jdbc:postgresql://localhost/droolsdb
Jun 14, 2008 8:58:12 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: connection properties: {user=droolsuser, password=****}
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: RDBMS: PostgreSQL, version: 8.2.5
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC driver: PostgreSQL Native Driver, version: PostgreSQL 8.2 JDBC3 with SSL (build 508)
Jun 14, 2008 8:58:12 AM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.PostgreSQLDialect
Jun 14, 2008 8:58:12 AM org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
INFO: Transaction strategy: org.hibernate.transaction.JDBCTransactionFactory
Jun 14, 2008 8:58:12 AM org.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup
INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic flush during beforeCompletion(): disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic session close at end of transaction: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch size: 15
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch updates for versioned data: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Scrollable result sets: enabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC3 getGeneratedKeys(): disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Connection release mode: auto
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default batch fetch size: 1
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Generate SQL with comments: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL updates by primary key: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL inserts for batching: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
Jun 14, 2008 8:58:12 AM org.hibernate.hql.ast.ASTQueryTranslatorFactory <init>
INFO: Using ASTQueryTranslatorFactory
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query language substitutions: {}
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JPA-QL strict compliance: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Second-level cache: enabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query cache: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory createCacheProvider
INFO: Cache provider: org.hibernate.cache.NoCacheProvider
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Optimize cache for minimal puts: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Structured second-level cache entries: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Echoing all SQL to stdout
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Statistics: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Deleted entity synthetic identifier rollback: disabled
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default entity-mode: pojo
Jun 14, 2008 8:58:12 AM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Named query checking : enabled
Jun 14, 2008 8:58:12 AM org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory
Jun 14, 2008 8:58:12 AM org.hibernate.impl.SessionFactoryObjectFactory addInstance
INFO: Not binding factory to JNDI, no JNDI name configured
Jun 14, 2008 8:58:12 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: Running hbm2ddl schema export
Jun 14, 2008 8:58:12 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: exporting generated schema to database
Jun 14, 2008 8:58:13 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: schema export complete
[BF3 with 15 levels for 139.99, BF2 with 5 levels for 39.99, AoE3 with 45 levels for 129.99]
[BF3 with 15 levels for 139.99, BF2 with 5 levels for 39.99]
Hibernate: select nextval ('player_id_seq')
Hibernate: select nextval ('game_id_seq')
Hibernate: select nextval ('game_id_seq')
Hibernate: select nextval ('game_id_seq')
Hibernate: select nextval ('player_id_seq')
Hibernate: insert into PLAYERS (NAME, AGE, PLAYER_ID) values (?, ?, ?)
Hibernate: insert into GAMES (NAME, PRICE, LEVELS, GAME_ID) values (?, ?, ?, ?)
Hibernate: insert into GAMES (NAME, PRICE, LEVELS, GAME_ID) values (?, ?, ?, ?)
Hibernate: insert into GAMES (NAME, PRICE, LEVELS, GAME_ID) values (?, ?, ?, ?)
Hibernate: insert into PLAYERS (NAME, AGE, PLAYER_ID) values (?, ?, ?)
Hibernate: insert into PLAYERS_GAMES (PLAYER_ID, GAME_ID) values (?, ?)
Hibernate: insert into PLAYERS_GAMES (PLAYER_ID, GAME_ID) values (?, ?)
Hibernate: insert into PLAYERS_GAMES (PLAYER_ID, GAME_ID) values (?, ?)
Hibernate: insert into PLAYERS_GAMES (PLAYER_ID, GAME_ID) values (?, ?)
Hibernate: insert into PLAYERS_GAMES (PLAYER_ID, GAME_ID) values (?, ?)
Hibernate: select this_.PLAYER_ID as PLAYER1_0_0_, this_.NAME as NAME0_0_, this_.AGE as AGE0_0_ from PLAYERS this_
2 player(s) found:
Hibernate: select games0_.PLAYER_ID as PLAYER1_1_, games0_.GAME_ID as GAME2_1_, game1_.GAME_ID as GAME1_2_0_, game1_.NAME as NAME2_0_, game1_.PRICE as PRICE2_0_, game1_.LEVELS as LEVELS2_0_ from PLAYERS_GAMES games0_ left outer join GAMES game1_ on games0_.GAME_ID=game1_.GAME_ID where games0_.PLAYER_ID=?
jarek has following games: [AoE3 with 45 levels for 129.99, BF3 with 15 levels for 139.99, BF2 with 5 levels for 39.99]
Hibernate: select games0_.PLAYER_ID as PLAYER1_1_, games0_.GAME_ID as GAME2_1_, game1_.GAME_ID as GAME1_2_0_, game1_.NAME as NAME2_0_, game1_.PRICE as PRICE2_0_, game1_.LEVELS as LEVELS2_0_ from PLAYERS_GAMES games0_ left outer join GAMES game1_ on games0_.GAME_ID=game1_.GAME_ID where games0_.PLAYER_ID=?
ewelina has following games: [BF3 with 15 levels for 139.99, BF2 with 5 levels for 39.99]
Hibernate: select game2_.GAME_ID as GAME1_2_, game2_.NAME as NAME2_, game2_.PRICE as PRICE2_, game2_.LEVELS as LEVELS2_ from PLAYERS player0_ inner join PLAYERS_GAMES games1_ on player0_.PLAYER_ID=games1_.PLAYER_ID inner join GAMES game2_ on games1_.GAME_ID=game2_.GAME_ID where player0_.AGE>=?
Hibernate: select players0_.GAME_ID as GAME2_1_, players0_.PLAYER_ID as PLAYER1_1_, player1_.PLAYER_ID as PLAYER1_0_0_, player1_.NAME as NAME0_0_, player1_.AGE as AGE0_0_ from PLAYERS_GAMES players0_ left outer join PLAYERS player1_ on players0_.PLAYER_ID=player1_.PLAYER_ID where players0_.GAME_ID=?
The game BF2is owned by [jarek, ewelina]
Hibernate: select players0_.GAME_ID as GAME2_1_, players0_.PLAYER_ID as PLAYER1_1_, player1_.PLAYER_ID as PLAYER1_0_0_, player1_.NAME as NAME0_0_, player1_.AGE as AGE0_0_ from PLAYERS_GAMES players0_ left outer join PLAYERS player1_ on players0_.PLAYER_ID=player1_.PLAYER_ID where players0_.GAME_ID=?
The game BF3is owned by [jarek, ewelina]
Hibernate: select players0_.GAME_ID as GAME2_1_, players0_.PLAYER_ID as PLAYER1_1_, player1_.PLAYER_ID as PLAYER1_0_0_, player1_.NAME as NAME0_0_, player1_.AGE as AGE0_0_ from PLAYERS_GAMES players0_ left outer join PLAYERS player1_ on players0_.PLAYER_ID=player1_.PLAYER_ID where players0_.GAME_ID=?
The game AoE3is owned by [jarek]
The game BF2is owned by [jarek, ewelina]
The game BF3is owned by [jarek, ewelina]
Artykuł przedstawił prosty i przyjemny sposób na integrację silnika reguł Drools z Hibernatem. Takie rozwiązanie pozwla na przeglądanie danych znajdujących się nie tylko w pamięci roboczej silnika reguł, ale także w relacyjnej bazie danych.
Możesz skomentować ten artykuł.