myHead

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.

  1. Tworzymy nowy projekt Drools
  2. Klasy
  3. Hibernate
  4. Drools
  5. Jak to działa?
  6. Wynik końcowy
  7. Podsumowanie

  1. 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".

  2. Menu File -> New -> Project -> Drools - > Rule Project -> Next. Podajemy nazwę projektu drools-hibernate-demo i wybieramy Next, aby odznaczyć przykładowe pliki

  3. Klasy
  4. 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;
    	}
    }	
    
  5. Hibernate
  6. 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:

    • 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

    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>
    
  7. Drools
  8. 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
    	
  9. Jak to działa?
  10. 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:

    • 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.

    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

  11. Efekt końcowy
  12. 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]	
    	
  13. Podsumowanie
  14. 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ł.