org.hibernate.WrongClassException 当通过具有抽象 class 继承的休眠加载实体时
org.hibernate.WrongClassException when loading entity via hibernate with abstract class inheritance
问题:
我是否需要删除接口 IAbstractUserService 上的泛型?
是否与类型擦除的答案有关?
问题:
我遇到了这个异常:
org.hibernate.WrongClassException: Object [id=1] was not of the specified subclass [com.faz.idb.models.Adviser] : loaded object was of wrong class class com.faz.idb.models.Customer
当尝试加载实体时:
T getUserByEmail(String email);
像这样:
AbstractUserServiceImpl<? extends AbstractUser> userService;
AbstractUser user = userService.getUserByEmail(email);
目前我有:
hibernate v7.0.3.Final
抽象 parent class : AbtrsactUser
Child classes:客户和顾问;
@Getter
@Setter
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "user_type", discriminatorType = DiscriminatorType.STRING)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(name = "customer", value = Customer.class),
@JsonSubTypes.Type(name = "adviser", value = Adviser.class)
})
@DiscriminatorOptions(force = true)
public abstract class AbstractUser { ........ }
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@DiscriminatorValue("adviser")
@DiscriminatorOptions(force = true)
public class Adviser extends AbstractUser { ........ }
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@DiscriminatorValue("customer")
@DiscriminatorOptions(force = true)
public class Customer extends AbstractUser { ........ }
服务:
public interface IAbstractUserService<T extends AbstractUser> {
T getUserByEmail(String email);
实施:
@Service public class AbstractUserServiceImpl<T extends AbstractUser> implements IAbstractUserService<T> {
@Autowired
private AbstractUserRepository<T> userRepository;
@Override
public T getUserByEmail(String email) {
return userRepository.findByEmail(email).orElse(null);
}
存储库:
@存储库
public interface AbstractUserRepository extends JpaRepository {
可选的 findByEmail(String email);
}
生成SQL:
Hibernate: select abstractus0_.id as id2_0_, abstractus0_.email as
email3_0_, abstractus0_.password as password4_0_,
abstractus0_.user_type as user_typ1_0_ from abstract_user abstractus0_
where abstractus0_.user_type in ('adviser', 'customer') and
abstractus0_.email=?
Hibernate: select person0_.customer_id as customer1_5_0_,
person0_.first_name as first_na2_5_0_, person0_.gender as
gender3_5_0_, person0_.last_name as last_nam4_5_0_, adviser1_.id as
id2_0_1_, adviser1_.email as email3_0_1_, adviser1_.password as
password4_0_1_ from person person0_ left outer join abstract_user
adviser1_ on person0_.customer_id=adviser1_.id where
person0_.customer_id=? 2022-03-14 06:14:34.029
INFO 79095 --- [nio-8080-exec-2]
o.h.e.internal.DefaultLoadEventListener : HHH000327: Error
performing load command
在我的数据库中我只有一个用户:
user_type |编号 |电邮 |密码
客户 | 1 | xyz@live.fr | ....
问题已解决。
我在@OneToOne 关系的子实体中使用不带@JoinColumn(name="id") 的@MapsId。
解释:
“AbstracUser”由“Customer”实体扩展,他与“PersonDetails”有@OneToOne 关系。
所以在客户中我有:
@OneToOne(mappedBy = "Customer", fetch = FetchType.LAZY,
cascade {CascadeType.ALL}, optional = false)
@PrimaryKeyJoinColumn private PersonDetails person;
和人物详细信息:
@MapsId()
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name="id")
private Customer customer;
解决方案是在
中添加引用的列
@MapsId("id")
或
@MapsId
@JoinColumn(name="id")
N.B
- 还要确保通过“设置”相应的对象来同步关系的双方。 (ressource I used)
- 为了更好的架构,我最终将 @OneToOne 关系放在“AbstractUser”实体中(而不是在 Customer 中)。
问题:
我是否需要删除接口 IAbstractUserService 上的泛型?
是否与类型擦除的答案有关?
问题:
我遇到了这个异常:
org.hibernate.WrongClassException: Object [id=1] was not of the specified subclass [com.faz.idb.models.Adviser] : loaded object was of wrong class class com.faz.idb.models.Customer
当尝试加载实体时:
T getUserByEmail(String email);
像这样:
AbstractUserServiceImpl<? extends AbstractUser> userService;
AbstractUser user = userService.getUserByEmail(email);
目前我有:
hibernate v7.0.3.Final
抽象 parent class : AbtrsactUser
Child classes:客户和顾问;
@Getter
@Setter
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "user_type", discriminatorType = DiscriminatorType.STRING)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(name = "customer", value = Customer.class),
@JsonSubTypes.Type(name = "adviser", value = Adviser.class)
})
@DiscriminatorOptions(force = true)
public abstract class AbstractUser { ........ }
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@DiscriminatorValue("adviser")
@DiscriminatorOptions(force = true)
public class Adviser extends AbstractUser { ........ }
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@DiscriminatorValue("customer")
@DiscriminatorOptions(force = true)
public class Customer extends AbstractUser { ........ }
服务:
public interface IAbstractUserService<T extends AbstractUser> {
T getUserByEmail(String email);
实施:
@Service public class AbstractUserServiceImpl<T extends AbstractUser> implements IAbstractUserService<T> {
@Autowired
private AbstractUserRepository<T> userRepository;
@Override
public T getUserByEmail(String email) {
return userRepository.findByEmail(email).orElse(null);
}
存储库:
@存储库
public interface AbstractUserRepository extends JpaRepository
生成SQL:
Hibernate: select abstractus0_.id as id2_0_, abstractus0_.email as email3_0_, abstractus0_.password as password4_0_, abstractus0_.user_type as user_typ1_0_ from abstract_user abstractus0_ where abstractus0_.user_type in ('adviser', 'customer') and abstractus0_.email=?
Hibernate: select person0_.customer_id as customer1_5_0_, person0_.first_name as first_na2_5_0_, person0_.gender as gender3_5_0_, person0_.last_name as last_nam4_5_0_, adviser1_.id as id2_0_1_, adviser1_.email as email3_0_1_, adviser1_.password as password4_0_1_ from person person0_ left outer join abstract_user adviser1_ on person0_.customer_id=adviser1_.id where person0_.customer_id=? 2022-03-14 06:14:34.029
INFO 79095 --- [nio-8080-exec-2] o.h.e.internal.DefaultLoadEventListener : HHH000327: Error performing load command
在我的数据库中我只有一个用户:
user_type |编号 |电邮 |密码
客户 | 1 | xyz@live.fr | ....
问题已解决。
我在@OneToOne 关系的子实体中使用不带@JoinColumn(name="id") 的@MapsId。
解释:
“AbstracUser”由“Customer”实体扩展,他与“PersonDetails”有@OneToOne 关系。
所以在客户中我有:
@OneToOne(mappedBy = "Customer", fetch = FetchType.LAZY,
cascade {CascadeType.ALL}, optional = false)
@PrimaryKeyJoinColumn private PersonDetails person;
和人物详细信息:
@MapsId()
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name="id")
private Customer customer;
解决方案是在
中添加引用的列@MapsId("id")
或
@MapsId
@JoinColumn(name="id")
N.B
- 还要确保通过“设置”相应的对象来同步关系的双方。 (ressource I used)
- 为了更好的架构,我最终将 @OneToOne 关系放在“AbstractUser”实体中(而不是在 Customer 中)。