Java/Hibernate中无关联多表连接实现方法咨询
解决Hibernate实体关联与查询的问题
刚上手Java/Hibernate项目遇到关联问题很正常,我来一步步帮你搞定UserBalanceLog和AdminLogin的关联,以及对应的查询调整:
1. 先给实体类建立关联映射
你现在的实体里只是存了adminId数值字段,没有和AdminLogin建立Hibernate的关联关系。我们用@ManyToOne注解来实现多对一关联(一个管理员可以对应多条余额操作日志):
修改后的UserBalanceLog实体代码:
@Entity @Table(name = "user_balance_log") public class UserBalanceLog { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private int userId; // 替换原来的int adminId,建立实体关联 @ManyToOne(fetch = FetchType.LAZY) // 懒加载,按需获取管理员数据,优化性能 @JoinColumn(name = "adminId") // 这里的name要和数据库表的外键字段名完全一致 private AdminLogin admin; private Float balance; private String balanceType; private String message; @Temporal(javax.persistence.TemporalType.DATE) private Date dateCreated; // 新增关联实体的getter/setter public AdminLogin getAdmin() { return admin; } public void setAdmin(AdminLogin admin) { this.admin = admin; } // 可选:如果需要单独获取adminId,保留这个方法不影响 public int getAdminId() { return admin != null ? admin.getId() : 0; } // 其他原有getter/setter保持不变... }
注意:如果你的数据库
user_balance_log表中外键字段是下划线命名(比如admin_id),记得把@JoinColumn的name改成"admin_id",要和实际数据库字段匹配。
2. 调整Criteria查询关联管理员信息
实体关联好之后,你可以在查询余额日志时,轻松关联查询管理员的信息,比如姓名、用户名等。我们需要在Criteria里创建关联别名来实现:
修改后的查询代码:
Session session = this.sessionFactory.getCurrentSession(); Criteria criteria = session.createCriteria(UserBalanceLog.class, "ubl"); // 创建AdminLogin的关联别名,用内连接只返回有对应管理员的日志 criteria.createAlias("ubl.admin", "admin", JoinType.INNER_JOIN); // 投影里可以添加管理员的字段,按需选择 criteria.setProjection(Projections.projectionList() .add(Projections.property("ubl.balance"),"balance") .add(Projections.property("ubl.balanceType"),"balanceType") .add(Projections.property("ubl.message"),"message") .add(Projections.property("ubl.dateCreated"),"dateCreated") .add(Projections.property("admin.firstName"),"adminFirstName") // 管理员名 .add(Projections.property("admin.lastName"),"adminLastName")); // 管理员姓 criteria.addOrder(Order.desc("ubl.id")); if (parameters.get("userId") != null) { criteria.add(Restrictions.eq("ubl.userId", new Integer(parameters.get("userId")))); } if (parameters.get("balanceType") != null) { criteria.add(Restrictions.eq("ubl.balanceType", parameters.get("balanceType"))); } if (parameters.get("dateCreated") != null) { criteria.add(Restrictions.eq("ubl.dateCreated", parameters.get("dateCreated"))); } // 可选:如果需要按管理员ID过滤,添加这个条件 // if (parameters.get("adminId") != null) { // criteria.add(Restrictions.eq("admin.id", new Integer(parameters.get("adminId")))); // } // 投影多字段返回的是Object数组,每个元素对应投影顺序 List<Object[]> userBalanceList = criteria.list();
如果你的需求只是关联实体,不需要在查询时返回管理员字段,那只需要完成第一步的实体修改即可,后续通过userBalanceLog.getAdmin()就能直接获取对应的管理员对象。
小补充
- 懒加载
FetchType.LAZY是默认值,显式写出来是提醒你:调用getAdmin()时Hibernate会单独发SQL查询管理员数据;如果需要一次性加载所有关联数据,可以改成FetchType.EAGER,但要注意性能影响。 - 如果你用的是新版本Hibernate,推荐尝试JPA标准的
CriteriaQueryAPI,但旧的Hibernate Criteria写法也完全能满足你的需求。
内容的提问来源于stack exchange,提问作者Ravinder Singh
相关产品推荐
相关产品推荐

