【问题标题】:Entity for joining multiple tables用于连接多个表的实体
【发布时间】:2013-07-01 14:05:00
【问题描述】:

我正在使用休眠条件查询框架来生成报告。我还必须提供排序和过滤。当数据仅限于单个实体时,一切正常。但是,我需要加入多个实体并将结果显示在一个表中。以下是实体:

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

【问题讨论】:

  • 您只需要聚合/连接的信息来显示,还是真的需要一个包含所有这些信息的表格?如果是第一种情况,您可以使用所需信息创建 DTO 并创建相应的查询。
  • 我必须汇总这些信息。但是我也想利用 Hibernate 的条件查询 api。创建 DTO 需要手动处理排序、过滤和分页。
  • 不,DTO 只是一个普通的 POJO,它只会保存您需要的信息/列。我将在答案中创建一个快速示例。

标签: java hibernate hibernate-criteria


【解决方案1】:

您应该创建一个 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

【讨论】:

    猜你喜欢
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多