Search code examples
javahibernatedrools

Drools Hibernate JPA Annotation Many to Many Example DRL


I'm new on Hibernate and Drools, I want that drools evaluate a rule for a given Person and fire only if person ID exist on a given table.

For example: If I have a

Table Called 'Person' with fields: personID='1015'. A table called 'likes' with fields: id=1, name=sports.

And a Intermediate Table Called 'personLikes' with fields: personID=1015, idLikes=1.

And I load three diferent Persons with: personID=1015, personID=1020, personID=1035.

On that case rule execute only for person code=1015.

Question is: How can I construct that rule?

Here are my code.

DRL FILE:

        rule healthy when    
            p: Person()
            i: Interes(nombre=="Sports")
            InteresPersonaId(persona==p,interes==i)
            //InteresesPersona(pk==ip)      

        then
            System.out.println("OK" + p.id + "LIKES" +i.nombre);


    end

DB:

            CREATE TABLE IF NOT EXISTS `screb`.`person` (
              `idPerson` VARCHAR(15) NOT NULL,
              `gender` CHAR(1) NULL DEFAULT NULL,
              `age` INT(11) NULL DEFAULT NULL,
              `estrato` INT(11) NULL DEFAULT NULL,
              `idLocalizacion` INT(11) NULL DEFAULT NULL,
              PRIMARY KEY (`idPerson`),
              INDEX `FK_location_idx` (`idLocalizacion` ASC),
              CONSTRAINT `FK_location`
                FOREIGN KEY (`idLocalizacion`)
                REFERENCES `screb`.`localizacion` (`idLocalizacion`)
                ON DELETE NO ACTION
                ON UPDATE NO ACTION)
            ENGINE = InnoDB
            DEFAULT CHARACTER SET = utf8;

            USE `screb` ;

            -- -----------------------------------------------------
            -- Table `screb`.`interes`
            -- -----------------------------------------------------
            CREATE TABLE IF NOT EXISTS `screb`.`interes` (
              `idInteres` INT(11) NOT NULL AUTO_INCREMENT,
              `nombre` VARCHAR(45) NULL DEFAULT NULL,
              `descripcion` VARCHAR(45) NULL DEFAULT NULL,
              PRIMARY KEY (`idInteres`))
            ENGINE = InnoDB
            DEFAULT CHARACTER SET = utf8;


            -- -----------------------------------------------------
            -- Table `screb`.`interesesxpersona`
            -- -----------------------------------------------------
            CREATE TABLE IF NOT EXISTS `screb`.`interesesxpersona` (
              `persona` VARCHAR(15) NOT NULL DEFAULT '',
              `Interes` INT(11) NOT NULL DEFAULT '0',
              PRIMARY KEY (`persona`, `Interes`),
              INDEX `FK_PERS_INT_idx` (`Interes` ASC),
              CONSTRAINT `FK_IN_PER`
                FOREIGN KEY (`persona`)
                REFERENCES `screb`.`person` (`idPerson`)
                ON DELETE NO ACTION
                ON UPDATE NO ACTION,
              CONSTRAINT `FK_PERS_INT`
                FOREIGN KEY (`Interes`)
                REFERENCES `screb`.`interes` (`idInteres`)
                ON DELETE CASCADE
                ON UPDATE CASCADE)
            ENGINE = InnoDB
            DEFAULT CHARACTER SET = utf8;   

Class to load facts:

public class Campaign {

            public static final void main(String[] args) {
                KieContainer kc =     KieServices.Factory.get().getKieClasspathContainer();
                KieSession ksession = kc.newKieSession("CampaignKS");

                PersonManager person = new PersonManager();
                List<Person> list = person.listEvents();
                for(Person p :list){
                    ksession.insert(p);
                }



                InteresManager interes = new InteresManager();
                List<Interes> listaIntereses = interes.listIntereses();
                for(Interes i :listaIntereses){
                    ksession.insert(i);
                }



                ksession.fireAllRules();

                ksession.dispose();

            }

        }

Mapping Classes:

      @Entity
                @Table(name="interes",schema="screb")
                public class Interes implements java.io.Serializable {

                public int idInteres;
                public String nombre;
                public String descripcion;
                public Set<InteresesPersona> interesesP = new HashSet<InteresesPersona>(0);


                public Interes(){}
                public Interes(int interes,String nombre, String descripcion){
                    this.idInteres=interes;
                    this.nombre=nombre;
                    this.descripcion=descripcion;
                }
                public Interes(int interes,String nombre, String descripcion, Set<InteresesPersona>interesesPersona){
                    this.idInteres=interes;
                    this.nombre=nombre;
                    this.descripcion=descripcion;
                    this.interesesP=interesesPersona;
                }

                @Id @GeneratedValue
                @Column(name="idInteres")
                public int getIdInteres() {
                    return idInteres;
                }
                public void setIdInteres(int idInteres) {
                    this.idInteres = idInteres;
                }
                @Column(name="nombre")
                public String getNombre() {
                    return nombre;
                }
                public void setNombre(String nombre) {
                    this.nombre = nombre;
                }
                @Column(name="descripcion")
                public String getDescripcion() {
                    return descripcion;
                }
                public void setDescripcion(String descripcion) {
                    this.descripcion = descripcion;
                }

                @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.interes")
                public Set<InteresesPersona> getInteresesP(){
                    return this.interesesP;

                }
                public void setInteresesP(Set<InteresesPersona> interesesPersona){
                    this.interesesP=interesesPersona;

                }   
            }

Class InteresesPersona (PersonLikes):

            @Entity
            @Table(name="interes_persona",schema = "screb")
            @AssociationOverrides({
                    @AssociationOverride(name = "pk.persona", 
                        joinColumns = @JoinColumn(name = "idPerson")),
                    @AssociationOverride(name = "pk.interes", 
                        joinColumns = @JoinColumn(name = "idInteres")) })

            public class InteresesPersona implements java.io.Serializable{


                public InteresPersonaId pk = new InteresPersonaId();
                private Date createdDate;

                public InteresesPersona(){}

                @EmbeddedId
                public InteresPersonaId getPk() {
                    return pk;
                }

                public void setPk(InteresPersonaId pk) {
                    this.pk = pk;
                }

                @Transient
                public Person getPersona() {
                    return getPk().getPersona();
                }

                public void setPersona(Person persona) {
                    getPk().setPersona(persona);
                }

                @Transient
                public Interes getInteres() {
                    return getPk().getInteres();
                }

                public void setInteres(Interes interes) {
                    getPk().setInteres(interes);
                }

                @Temporal(TemporalType.DATE)
                @Column(name = "createdDate", nullable = false, length = 10)
                public Date getCreatedDate() {
                    return this.createdDate;
                }

                public void setCreatedDate(Date createdDate) {
                    this.createdDate = createdDate;
                }


                public boolean equals(Object o) {
                    if (this == o)
                        return true;
                    if (o == null || getClass() != o.getClass())
                        return false;

                    InteresesPersona that = (InteresesPersona) o;

                    if (getPk() != null ? !getPk().equals(that.getPk())
                            : that.getPk() != null)
                        return false;

                    return true;
                }

                public int hashCode() {
                    return (getPk() != null ? getPk().hashCode() : 0);
                }


            }

Class InteresesPersonaID (PersonLikesID)

            @Embeddable

            public class InteresPersonaId implements java.io.Serializable {

                public Person persona;
                public Interes interes;

                @ManyToOne
                public Person getPersona() {
                    return persona;
                }

                public void setPersona(Person persona) {
                    this.persona = persona;
                }

                @ManyToOne
                public Interes getInteres() {
                    return interes;
                }

                public void setInteres(Interes interes) {
                    this.interes = interes;
                }

                public boolean equals(Object o) {
                    if (this == o) return true;
                    if (o == null || getClass() != o.getClass()) return false;

                    InteresPersonaId that = (InteresPersonaId) o;

                    if (persona != null ? !persona.equals(that.persona) : that.persona!= null) return false;
                    if (interes != null ? !interes.equals(that.interes) : that.interes != null)
                        return false;

                    return true;
                }

                public int hashCode() {
                    int result;
                    result = (persona != null ? persona.hashCode() : 0);
                    result = 31 * result + (interes != null ? interes.hashCode() : 0);
                    return result;
                }


            }

Class Person

            @Entity
            @Table(name="person",schema="screb")

            public class Person implements java.io.Serializable{

                public String id;
                public char gender;
                public int age;
                public int estrato;
                public Set<InteresesPersona> interesesP = new HashSet<InteresesPersona>(0);


                public Person(){}
                public Person(String id,char genero,int edad,int estrato){
                    this.id=id;
                    this.gender=genero;
                    this.age=edad;
                    this.estrato=estrato;
                }
                public Person(String id,char genero,int edad,int estrato,Set<InteresesPersona>interesesPersona){
                    this.id=id;
                    this.gender=genero;
                    this.age=edad;
                    this.estrato=estrato;
                    this.interesesP = interesesPersona;
                }

                @Id 
                @Column(name="idPerson")
                public String getId() {
                    return id;
                }


                public void setId(String id) {
                    this.id = id;
                }

                @Column(name="gender")
                public char getGender() {
                    return gender;
                }


                public void setGender(char gender) {
                    this.gender = gender;
                }

                @Column(name="age")
                public int getAge() {
                    return age;
                }


                public void setAge(int age) {
                    this.age = age;
                }

                @Column(name="estrato")
                public int getEstrato() {
                    return estrato;
                }


                public void setEstrato(int estrato) {
                    this.estrato = estrato;
                }    

                @OneToMany(fetch = FetchType.LAZY, mappedBy= "pk.persona",cascade=CascadeType.ALL)
                public Set<InteresesPersona> getInteresesP(){
                    return this.interesesP;

                }

                public void setInteresesP(Set<InteresesPersona> interesesPersona){
                    this.interesesP=interesesPersona;

                }

                @Override
                public boolean equals(Object o){
                    if(this==o){return true;}
                    if(o==null||getClass()!=o.getClass()){return false;}

                    Person person = (Person) o;

                    if (!id.equals(person.id)){return false;}
                    if (gender!=person.gender){return false;}
                    if (age!=person.age){return false;}
                    if (estrato!=person.estrato){return false;}

                    return true;

                }

                @Override
                public int hashCode(){
                    int result = id.hashCode();


                    return result;
                }

            }

Class PersonManager:

        public class PersonManager {
             public List listEvents(){
                Session session= HibernateUtil.getSessionFactory().getCurrentSession();
                session.beginTransaction();
                Query query= session.createQuery("from Person");
                List<Person> list = query.list();       
                session.getTransaction().commit();



                return list;
            }
            }

Solution

  • Your Java classes are somewhat redundant. This doesn't matter for writing rules but it may affect DB access. - Is InteresesPersona different from InteresesPersonaId?

    rule "a person's interests a"
    when
        Person( $id: id, $pip: interesesP ) 
        $ip: InteresesPersona() from $pip
        Interes( interesesP contains $ip, $nom: nombre )
    then
        System.out.println( $id + " likes " + $nom );
    end
    

    Fires for each combination of person and interest, grouped by persons. (Rearrange to have it grouped by interest.)

    If you would insert InteresesPersonaId objects you could also write

    rule  "a person's interests b"
    when
        $ip: InteresesPersonaId( $p: persona, $i: interes)
        Person( this == $p, $id: id ) 
        Interes( this == $i, $nom: nombre )
    then
        System.out.println( $id + " likes " + $nom );
    end
    

    But note that this rule may produce results in a random order, i.e., not grouped by person.