0

I have the following table with 3 types of people, boy, man and woman:

CREATE TABLE IF NOT EXISTS person(
  id int unsigned NOT NULL AUTO_INCREMENT,
  type VARCHAR(100),
  name VARCHAR(100),
  description VARCHAR(2000),
  PRIMARY KEY (id) 
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

INSERT INTO person (id, type, name, description) VALUES(1, 'child', 'Omar', '');
INSERT INTO person (id, type, name, description) VALUES(2, 'man', 'john doe', '');
INSERT INTO person (id, type, name, description) VALUES(3, 'woman', 'jennifer lopez', '');

And I have the following classes:

@MappedSuperclass
public class PersonEntity {

    @Id
    @GeneratedValue
    @Column(name="id")      
    private Integer id;

    @Column(name="name")        
    private String name;

    @Column(name="description")         
    private String desciption;

    /**
     * @return the id
     */
    public final Integer getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public final void setId(final Integer id) {
        this.id = id;
    }

    /**
     * @return the name
     */
    public final String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public final void setName(final String name) {
        this.name = name;
    }

    /**
     * @return the desciption
     */
    public final String getDesciption() {
        return desciption;
    }

    /**
     * @param desciption the desciption to set
     */
    public final void setDesciption(final String desciption) {
        this.desciption = desciption;
    }

}

@Entity
@Table(name = "person")
public class ChildEntity extends PersonEntity {

    //Value child
    @Column(name="type")        
    private String type;

    /**
     * @return the type
     */
    public String getType() {
        return type;
    }

    /**
     * @param type the type to set
     */
    public void setType(String type) {
        this.type = type;
    }

}

@Entity
@Table(name = "person")
public class ManEntity extends PersonEntity {

    //Value man
    @Column(name="type")        
    private String type;

    /**
     * @return the type
     */
    public String getType() {
        return type;
    }

    /**
     * @param type the type to set
     */
    public void setType(String type) {
        this.type = type;
    }   
}

@Entity
@Table(name = "person")
public class WomanEntity extends PersonEntity {

    //Value man
    @Column(name="type")        
    private String type;

    /**
     * @return the type
     */
    public String getType() {
        return type;
    }

    /**
     * @param type the type to set
     */
    public void setType(String type) {
        this.type = type;
    }       
}

My question is how can I make my list of loaded classes directly discriminated by the kind of person with annotations. Ie to recover all women, just come to me kind of woman. I do so because they have all three the same attributes and do not want to make just one person class and method search by type.


I found the solution:

@Entity  
@Table(name = "person")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type", discriminatorType = DiscriminatorType.STRING)
public abstract class PersonEntity {

    @Id
    @GeneratedValue
    @Column(name="id")      
    private Integer id;

    @Column(name="name")        
    private String name;

    @Column(name="description")         
    private String desciption;

    @Column(name="type", insertable = false, updatable = false)         
    private String type;    

    //getters and setters
}

@Entity
@Table(name = "person")
@DiscriminatorValue("child")
public class ChildEntity extends PersonEntity { 

}

@Entity
@Table(name = "person")
@DiscriminatorValue(value="man")
public class ManEntity extends PersonEntity {

}

@Entity  
@Table(name = "person")
@DiscriminatorValue(value="woman")
public class WomanEntity extends PersonEntity {

}
oscar
  • 1,636
  • 6
  • 31
  • 59

2 Answers2

0

You can use inheritance strategy InheritanceType.SINGLE_TABLE. For that u need to annotate your PersonEntity class as follows:

@Entity  
@Table(name = "person")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type",discriminatorType=DiscriminatorType.STRING) 
public abstract class PersonEntity {
...
}

I think you need to declare it abstract as well, but I'm not 100% sure.

Then your subclasses need following annotation:

@Entity
@DiscriminatorValue(value="child")  
public class ChildEntity extends PersonEntity {
...
}

@Entity
@DiscriminatorValue(value="man")  
public class ManEntity extends PersonEntity {
...
}

@Entity
@DiscriminatorValue(value="woman")  
public class WomanEntity extends PersonEntity {
...
}
sfrutig
  • 277
  • 2
  • 14
  • I was just trying something like that, but not work for me, I always returns an empty list. – oscar May 23 '15 at 12:21
  • How does your query looks like? – sfrutig May 23 '15 at 12:26
  • Does not leave any query in the log, I suppose that no query does not run. – oscar May 23 '15 at 12:57
  • But how do you load them? Can you post your code for fetching the entities? – sfrutig May 23 '15 at 13:09
  • In my genericDaoImpl @Override @SuppressWarnings("unchecked") public final listAll listar(final Class type) throws PersistenceException { Session sesion = sessionFactory.getCurrentSession(); final Criteria crit = sesion.createCriteria(type); List resultado = null; try { resultado = crit.list(); } catch (HibernateException ex) { throw new PersistenceException(ex); } return resultado; } – oscar May 23 '15 at 13:34
  • Yes. But I returned three empty lists, children, men and women. And in the log does not leave any query. – oscar May 23 '15 at 16:08
  • I added @DiscriminatorOptions(force = true), but not working. I changed the criteria for implementing this: public final List listar(final Class type) throws PersistenceException { Session sesion = sessionFactory.getCurrentSession(); List resultado = null; resultado = sesion.createQuery("FROM " + type.getSimpleName()).list(); return resultado; } and throws me the following exception: org.hibernate.hql.internal.ast.QuerySyntaxException: ChildEntity is not mapped [FROM ChildEntity] – oscar May 23 '15 at 16:35
  • Did you list the entities in your hibernate config? (see [this stackoverflow question](http://stackoverflow.com/a/8524836/3843672/) ) – sfrutig May 23 '15 at 18:45
  • This is my setup: ${hibernate.hbm2ddl.auto} ${hibernate.dialect} true – oscar May 23 '15 at 19:04
  • What about the second suggestion in the above link? Do you use javax...Entity? – sfrutig May 24 '15 at 05:34
  • I found the solution, I have to put the "table" annotation also child, man and woman. And in the attribute type insertable = false, updatable = false – oscar May 24 '15 at 16:52
0

I found the solution:

@Entity  
@Table(name = "person")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type", discriminatorType = DiscriminatorType.STRING)
public abstract class PersonEntity {

    @Id
    @GeneratedValue
    @Column(name="id")      
    private Integer id;

    @Column(name="name")        
    private String name;

    @Column(name="description")         
    private String desciption;

    @Column(name="type", insertable = false, updatable = false)         
    private String type;    

    //getters and setters
}

@Entity
@Table(name = "person")
@DiscriminatorValue("child")
public class ChildEntity extends PersonEntity { 

}

@Entity
@Table(name = "person")
@DiscriminatorValue(value="man")
public class ManEntity extends PersonEntity {

}

@Entity  
@Table(name = "person")
@DiscriminatorValue(value="woman")
public class WomanEntity extends PersonEntity {

}
oscar
  • 1,636
  • 6
  • 31
  • 59