2013-07-01 29 views
0

我正在使用hibernate標準查詢框架來生成報告。我必須提供分類和過濾功能。當數據侷限於單個實體時,情況正常。但是我有一個要求加入多個實體並在一個表中顯示結果。以下是實體:加入多個表的實體

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

這些實體具有通用的用戶名。是否有可能創建一個沒有表但只包含這些實體作爲字段的實體?例如:

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

我可以創建一個映射表,但我把它作爲最後的手段。

編輯

,我想火的查詢是這樣的:

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

你只需要顯示的彙總/合併的信息或者你真的需要一臺與所有的信息?如果是第一種情況,您可以創建一個包含所需信息的DTO並創建相應的查詢。 –

+0

我必須彙總此信息。不過,我也想利用Hibernate的標準查詢API。創建DTO將需要手動處理排序,過濾和分頁。 – Vaibhav

+0

不,DTO只是一個普通的POJO,它只能容納你需要的信息/列。我將在答案中創建一個快速示例。 –

回答

2

您應該創建一個POJO的DTO將舉行正是你所需要的信息,並使用它的實際的實體。假設我們有三個實體,OrderOrderItemCustomer和查詢應該是這樣的

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'; 

現在,DTO是:

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 
} 

而在你的DAO,你可以做沿東西以下幾行:

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(); 

顯然,您不能將項目保存在返回的列表中,但您完全可以獲取信息你想要的,你仍然可以處理列表中的東西,你不能用SQL/Criteria API處理。

更新:剛發現這個環節,這也可能與我上面所用的概念幫助: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