Hibernate5.6+Spring5.3中无法定位userName属性的问题求助
Hibernate 5.6 + Spring 5.3中Criteria API无法识别复合ID属性的问题
问题场景
在Hibernate 5.6搭配Spring 5.3环境下,使用Criteria API查询UmsUserRoleVOImpl实体时,尝试通过root.get("userName")获取属性触发异常,尽管实体类中存在该属性且已通过hbm.xml完成映射。
错误信息
java.lang.IllegalArgumentException: Unable to locate Attribute with the given name [userName] on this ManagedType [com.myapp.ums.business.impl.UmsUserRoleVOImpl]
相关代码
1. Criteria查询代码
CriteriaBuilder cb = this.getSession().getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(aliasToBeanClass); Root root = cq.from(aliasToBeanClass); // aliasToBeanClass设置为UmsUserRoleVOImpl predicates.add(cb.equal(root.get(key), value)); // key设置为"userName" - 此行触发异常
2. Hibernate映射文件(hbm.xml)
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.myapp.ums.business.impl.UmsUserRoleVOImpl" table="ums_t_user_role" proxy="com.myapp.ums.common.business.UmsUserRoleVO"> <composite-id> <key-property name="userName" type="java.lang.String" column="fk_user_id"/> <key-property name="roleName" type="java.lang.String" column="fk_role_id"/> </composite-id> </class> </hibernate-mapping>
3. UmsUserRoleVOImpl核心代码
public class UmsUserRoleVOImpl extends AbstractBasePropertiesImpl implements UmsUserRoleVO { private static final long serialVersionUID = 2393634151578825216L; private String roleName; private String userName; private List<PmPropertyVO> properties; // 父类方法与其他省略代码... @Get(UmsUserRoleVO.USER_NAME) public String getUserName() { return this.userName; } @Set(UmsUserRoleVO.USER_NAME) public void setUserName(String userName) { this.userName = userName; } @Get(UmsUserRoleVO.ROLE_NAME) public String getRoleName() { return roleName; } @Set(UmsUserRoleVO.ROLE_NAME) public void setRoleName(String roleName) { this.roleName = roleName; } }
原因分析
- 复合ID的元数据封装规则:Hibernate会将
<composite-id>中的属性整体封装为一个单独的ID属性(默认名称为id),而非将其作为实体的普通属性。直接使用root.get("userName")访问会绕过ID属性的层级,导致无法找到对应属性。 - 映射文件未正确加载:如果hbm.xml文件未被Spring或Hibernate的配置扫描到,实体的元数据不会包含这些属性,也会触发该异常。
- 自定义注解的兼容性:实体类使用了自定义的
@Get/@Set注解而非JPA标准注解,若Hibernate元数据处理器无法识别这些注解,可能导致属性解析异常。
解决方案
方案1:通过复合ID层级访问属性
针对复合ID中的属性,需要通过ID属性的路径进行访问,默认情况下使用id作为复合ID的名称:
predicates.add(cb.equal(root.get("id").get("userName"), value));
如果在hbm.xml中给<composite-id>设置了name属性(比如name="userRoleId"),则使用对应的名称访问:
predicates.add(cb.equal(root.get("userRoleId").get("userName"), value));
方案2:确保映射文件被正确加载
检查Spring配置,确保hbm.xml所在路径被纳入扫描范围。示例配置:
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="mappingLocations" value="classpath:com/myapp/ums/business/impl/*.hbm.xml"/> <!-- 其他数据源、hibernate属性配置 --> </bean>
方案3:验证自定义注解兼容性
临时替换自定义注解为JPA标准注解(如@Column)进行测试,确认是否是注解解析问题;若必须使用自定义注解,需确保Hibernate的元数据处理器能正确识别这些注解的逻辑。
内容的提问来源于stack exchange,提问作者d00d
相关产品推荐
相关产品推荐

