Hibernate中如何通过复合键查询数据?遇空值问题求助
Hey there! Let’s figure out why your Hibernate query with composite keys is returning nulls. I’ve tackled similar issues plenty of times, so let’s walk through the most common fixes step by step:
First off, your Role_PermissionId embeddable class needs to follow Hibernate’s rules for composite keys—miss any of these, and you’ll get unexpected nulls:
- It must be a public class with a no-arg constructor (Hibernate needs this to instantiate it)
- It needs properly overridden
equals()andhashCode()methods (Hibernate uses these to compare composite key equality) - It should implement
Serializable(required for Hibernate to handle the key correctly)
Here’s a correct example:
@Embeddable public class Role_PermissionId implements Serializable { private Long roleId; private Long permissionId; // Required no-arg constructor public Role_PermissionId() {} // Convenience constructor (optional but helpful) public Role_PermissionId(Long roleId, Long permissionId) { this.roleId = roleId; this.permissionId = permissionId; } // Getters and Setters @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Role_PermissionId that = (Role_PermissionId) o; return Objects.equals(roleId, that.roleId) && Objects.equals(permissionId, that.permissionId); } @Override public int hashCode() { return Objects.hash(roleId, permissionId); } }
Make sure your RolePermission entity (the one mapped to roles_permissions table) correctly links the embeddable ID to your Role and Permission associations. The @MapsId annotation is critical here—it tells Hibernate which part of the composite key maps to the associated entity’s primary key.
Example mapping:
@Entity @Table(name = "roles_permissions") public class RolePermission { @EmbeddedId private Role_PermissionId id; @ManyToOne @MapsId("roleId") // Maps the roleId field in your embeddable ID to this Role's PK @JoinColumn(name = "role_id") private Role role; @ManyToOne @MapsId("permissionId") // Maps the permissionId field to this Permission's PK @JoinColumn(name = "permission_id") private Permission permission; // Constructors, getters, setters }
Forgetting @MapsId is one of the most common reasons queries return null—Hibernate can’t correlate the composite key fields to the associated entities without it.
Double-check that your query is referencing the composite key fields correctly:
- JPQL Query: Make sure you’re accessing the embeddable ID’s properties properly:
String jpql = "SELECT rp FROM RolePermission rp WHERE rp.id.roleId = :roleId"; Query query = entityManager.createQuery(jpql); query.setParameter("roleId", 1L); List<RolePermission> results = query.getResultList(); find()Method: If usingentityManager.find(), ensure yourRole_PermissionIdhas valid, matching values for the database:Role_PermissionId lookupId = new Role_PermissionId(1L, 2L); RolePermission result = entityManager.find(RolePermission.class, lookupId);- Native SQL: Confirm your table and column names match exactly what’s in your database (case sensitivity matters in some databases like PostgreSQL).
Sometimes the simplest fix is the right one—check if the data you’re querying actually exists in the database. Run a raw SQL query directly to verify:
SELECT * FROM roles_permissions WHERE role_id = 1 AND permission_id = 2;
If this returns no rows, Hibernate returning null is expected—you’ll need to populate the data first.
Turn on SQL logging to see exactly what Hibernate is executing. This helps spot typos in queries, mismatched parameters, or unexpected mapping issues. Add these properties to your config:
spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true
Compare the generated SQL to what you’d manually run—any discrepancies (like wrong column names) will jump out immediately.
内容的提问来源于stack exchange,提问作者Nethre Paidi

