myHead

Jarosław Kijanowski


Drools meets Hibernate

Abstract:

Drools evaluates facts which are present in the working memory. But could it also reason over data stored in a relational database? This feature would extend Drools' range of applicability and since this is an often asked question in the mailing list, it's worth to know the answer which sounds: "of course Drools can!".

Hibernate, one of the most favorite ORM tools, allows to handle data stored in a relational database. This article will describe how one can access a Hibernate session from inside the rule engine. I will use PostgreSQL as a data source. Besides that I will create two classes, Game and Player, having a many-to-many relationship.

  1. Creating a new Drools project
  2. Class files
  3. Hibernate
  4. Drools
  5. How does it work?
  6. Results
  7. Summary

  1. Creating a new Drools project

    You still don't have installed the Drools 4.0.7 Eclipse Workbench? Just have a look at this article: "Rules fall from your eyes".

  2. Menu File -> New -> Project -> Drools - > Rule Project -> Next. Provide the project's name, drools-hibernate-demo, and click on Next, to uncheck the example files

  3. Class files
  4. Create a package "eu.kijanowski.drools.hibernate" in the src/main/java directory. We will use two class files, Player.java and Game.java. They have a many-tom-many relationship, since one player can own many games and one game can be owned by many players ;)

    Class 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;
    	}
    }
    	

    Class 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. Without going into details, download the binaries, Hibernate Core 3.2.6 and extract the archive.

    In our project create a directory called lib and copy over following files:

    • 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

    Now we have to add these libraries to the "build path": from the menu choose Project -> Properties -> Java Build Path -> Libraries and then Add External JARs and navigate to the project's lib directory. Mark all files and click OK.

    It's time to configure Hibernate. In the src/main/java directory create a file called 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>
     

    As you see, we're going to use the org.postgresql.Driver class, hence we need to add another library to our project. From the PostgreSQL home page we can download the required driver. I'm using 8.2-508 JDBC 3. Don't forget to add it to the Java Build Path, like we did with the hibernate library.

    It's time to download and start PostgreSQL and create a user and schema.

    /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

    The last step is mapping - this is connecting the world of Java objects with the world of relations (tabels). Create model.hbm.xml in the eu.kijanowski.drools.hibernate package:

    <?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. We're almost there. We olny have to create the rule file and a testing class which will start our example. But how are we going to use Hibernate in our application? Well, in our testing class we will create a Hibernate session and provide it to the rule engine's working memory as a constant global value. This allows us to access the database from inside the rule file. Next we will create a query and access the result's objects using the keyword "from". Let's do this:

    Class 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;
    	}
    
    }
    
    	

    The rule file can be created using the drools plug-in. Just click on the src/main/rules directory and from the menu File -> New -> Other... click 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. How does it work?
  10. Let's have a look at the global keyword in the rule file. This allows us to provide the rule engine with constants and variables from outside. Potential usecases are:

    • return results back to the application

    • access services, like Hibernate, JMS, file writers, email senders, etc.

    What's worth to know is that you should never change a global, when you use it in the condition part (LHS) of a rule. Moreover globals are not designed to share any data between rules, this can be done via facts living in the working memory.

    The condition element from allows to access data from other sources than the working memory. These can be Collectins, Maps and results coming from called methods. In our scenario we've created a query and received a list of games.

  11. Results
  12. After running our example (Run as -> Java Application) the console will show:

    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. Summary
  14. This article shows how you can easily integrate Hibernate with the Drools rule engine. This allows you to reason over data, which does not only live in the working memory, but also in an external database.

Feel free to leave a comment.