2013-07-01 5 views
0

J'utilise la structure de requête de critères d'hibernation pour générer des rapports. Je dois également assurer le tri et le filtrage. Les choses fonctionnaient bien lorsque les données étaient confinées à une seule entité. Cependant, j'ai besoin de joindre plusieurs entités et montrer le résultat dans une seule table. Les entités suivantes sont les suivantes:Entité pour joindre plusieurs tables

@Entity 
@Table(name = "user_profile") 
@Where(clause = "deleted = 0") 
public class UserProfile { 

    @GeneratedValue(strategy = GenerationType.AUTO) 
    Long id; 

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

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

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

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

    @Column(name = "last_name") 
    private String lastName;   
} 

@Entity 
@Table(name = "user_data") 
public class UserData { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

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

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

    @Column(name = "account_nonexpired") 
    private Boolean accountNonExpired = true; 

    @Column(name = "account_nonlocked") 
    private Boolean accountNonLocked = true; 

    @Column(name = "credentials_nonexpired") 
    private Boolean credentialsNonExpired = true; 

    @Column(name = "enabled") 
    private Boolean enabled = false; 
} 

@Entity 
@Table(name = "user_role") 
public class Role { 
    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

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

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

Ces entités ont un nom d'utilisateur commun. Est-il possible de créer une entité qui n'a pas de table mais qui ne contient que ces entités en tant que champs? Pour exemple:

public Class UserDataProfileRoleMapping{ 
    private UserProfile userProfile; 
    private List<Role> role; 
    private UserData userData; 
} 

Je peux créer une table de correspondance, mais je gardais en dernier recours.

Modifier

La requête que je veux tirer est quelque chose comme:

select * from user_data u, user_role r, user_profile up 
where 
u.username = r.username and 
r.username = up.username; 
+0

Avez-vous besoin que les informations agrégées/jointes pour l'affichage ou avez-vous vraiment besoin d'une table avec toutes ces informations ? Si c'est le premier cas, vous pouvez créer un DTO avec les informations dont vous avez besoin et créer une requête respective. –

+0

Je dois agréger cette information. Cependant, je veux également tirer parti de l'API de critères de Hibernate. La création d'un DTO implique la gestion manuelle du tri, du filtrage et de la pagination. – Vaibhav

+0

Non, le DTO n'est qu'un simple POJO qui ne contient que les informations/colonnes dont vous avez besoin. Je vais créer un exemple rapide dans une réponse. –

Répondre

2

Vous devez créer un POJO comme DTO qui contiendra exactement les informations dont vous avez besoin et utiliser à la place de les entités réelles. Supposons que nous avons trois entités, Order, OrderItem et Customer et la requête doit être quelque chose comme

SELECT Order.orderDate, Customer.name, OrderItem.amount 
FROM Order 
JOIN Customer ON Order.customerId = Customer.id 
JOIN OrderItem ON Order.id = OrderItem.orderId 
WHERE OrderItem.name = 'Puppet'; 

Maintenant, le DTO serait:

public class ReturnDto { 
    private Date date; 
    private String customerName; 
    private int amount; 

    public ReturnDto(Date date, String customerName, int amount) { 
     this.date = date; 
     ... 
    } 

    // getters for the three properties 
} 

Et dans votre DAO, vous pouvez faire quelque chose le long de la lignes suivantes:

CriteriaBuilder cb = getEntityManager().getCriteriaBuilder(); 
CriteriaQuery<ReturnDto> cQuery = cb.createQuery(ReturnDto.class); 

Root<Order> orderRoot = cQuery.from(Order.class); 
Join<Order, Customer> customerJoin = orderRoot.join(Order_.customer); 
Join<Order, OrderItem> orderItemJoin = orderRoot.join(Order_.orderItems); 

List<Predicate> criteria = new ArrayList<Predicate>(); 

criteria.add(cb.equal(orderItemJoin.get(OrderItem_.name), "Puppet"); 

// here you can do the sorting, e.g. - all with the criteria API! 
cQuery.orderBy(...); 
cQuery.distinct(true); 

cQuery.select(cb.construct(ReturnDto.class, 
    orderRoot.get(Order_.date), 
    customerJoin.get(Customer_.name), 
    orderItemJoin.get(OrderItem_.amount) 
)); 

cQuery.where(cb.and(criteria.toArray(new Predicate[criteria.size()]))); 
List<ReturnDto> returnList = entityManager.createQuery(cQuery).getResultList(); 

de toute évidence, vous ne pouvez pas enregistrer les articles dans la liste retournée, mais vous obtenez exactement les informations vous voulez et vous pouvez toujours gérer les choses avec la liste, que vous ne pouvez pas gérer avec l'API SQL/Criteria.

Mise à jour: Juste trouvé ce lien, qui peut aussi aider avec le concept je ci-dessus: http://www.javacodegeeks.com/2013/04/jpa-2-0-criteria-query-with-hibernate.html?utm_content=buffer0bd84&utm_source=buffer&utm_medium=twitter&utm_campaign=Buffer