2012-01-29 4 views
1

je les classes de modèle suivants:logique OU entre un critère et critères

@Entity 
@Table(name = "title") 
public final class Title extends ModelData<Title> 
{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Integer titleID; 

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

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

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "title") 
    private Set<Book> books; 
} 

@Entity 
@Table(name = "book") 
public final class Book extends ModelData<Book> 
{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "bookID") 
    private int bookID; 

    @ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER) 
    @JoinColumn(name = "titleID") 
    private Title title; 

    @Column(name = "edition") 
    private Integer edition; 

    @Column(name = "isbn") 
    private String ISBN; 
} 

Je veux écrire une requête de critères qui équivaut à l'instruction SQL suivante;

Select 
     t.title, b.edition 
    from 
     books b, title t 
    where 
     b.titleID = t.titleID 
    and 
     (b.edition=4 OR t.title LIKE '%Java%); 

J'ai essayé les éléments suivants:

Criteria c = session.createCriteria(Book.class); 

Criteria titleCriteria = c.createCriteria("title"); 
titleCriteria.add(Restrictions.like("title", "%Java%"); 

Criterion edition = Restrictions.eq("edition", 4); 

LogicalExpression orExp = Restrictions.or(edition, titleCriteria); //cannot do this 

Comment puis-je obtenir ce qui précède?

Merci.

Répondre

1
public class MyDTO { 
    private String dtoTitle; 
    private String dtoEdition; 
    // + setters/getters 
} 


Criteria c = session.createCriteria(Book.class,"b"); 
c.createAlias("title", "t"); 
c.add(
    Restrictions.disjunction() 
    .add(Restrictions.like("t.title", "%Java%")) 
    .add(Restrictions.eq("b.edition", 4)) 
); 
c.setProjection( 
    Projections.projectionList() 
    .add(Projections.property("t.title"), "dtoTitle") 
    .add(Projections.property("b.edition"), "dtoEdition") 
); 
c.setResultTransformer(Transformers.aliasToBean(MyDTO.class)); 
List<MyDTO> result = (List<MyDTO>)c.list(); 

Quelque chose comme cela fonctionne bien.

Sur dao utilisant de nombreux critères, vous devriez envisager d'utiliser des importations statiques.

0

Je pense que vous voulez cela. Je ne l'ai pas testé, donc il peut y avoir quelques erreurs mineures, mais l'idée de base est correcte.

Criteria c = session.createCriteria(Book.class); 
Criterion titleCriterion = Restrictions.like("title.title", "%Java%"); 
Criterion edition = Restrictions.eq("edition", 4); 
c.add(Restrictions.or(edition, titleCriterion)); 
+0

Etes-vous sûr de pouvoir ajouter des Restrictions aux entités associées comme vous l'avez fait bove. J'ai essayé le ci-dessus, et je reçois l'exception suivante: 'org.hibernate.QueryException: n'a pas pu résoudre la propriété: title.title de: com.maximus.db.model.Book' –

+0

Oui, j'ai fait ce genre de chose dans le passé, donc je ne peux pas voir pourquoi cela ne fonctionne pas. Incidemment, y a-t-il une raison pour laquelle vous ne pouvez pas utiliser HQL pour cette requête? Cela pourrait être plus simple de le faire. –

0

Pour plus de 2 ou conditions, il est plus lisible à utiliser:

c.add(
    Restrictions.disjunction() 
      .add(Restrictions.eq(...)) 
      .add(Restrictions.eq(...)) 
      .add(Restrictions.eq(...)) 
    ) 
1

Une autre idée

Convertir critères yout champ de formule et d'évaluer criterios normalement

Ajouter un champ de formule fichier de mappage ou annotations à vos classes

<property name="titlename" type="string" 
formula="(Select title.title from title 
    where title.titleID= titleID)"/> 

puis

Criteria c = session.createCriteria(Book.class) 
Criteria titleCriteria = c.createCriteria("title"); 
titleCriteria.add(Restrictions.like("titlename", "%Java%"); 
Criterion edition = Restrictions.eq("edition", 4); 
LogicalExpression orExp = Restrictions.or(edition, titleCriteria); //CAN< do this!!! 
Questions connexes