hibernate 的保存,更新,删除都是通过触发一系列相关事件来处理的,对于一对一关系,在A表a,b为联合主键对应hibernate实体为A.id,B表中a,b同样联合主键对应hibernate实体为B.id且a,b的外键关联A表于是就有了一对一关系。
当取得对象B的时候触发DefaultLoadEventListener时间处理,这时传过来的ID,为A.id,但是在B的对象生成的时候确实需要B.id出现类型不匹配
解决方案:重写DefaultLoadEventListener修改事件传过来的A.id为B.id
代码
public class MyLoadEventListener extends DefaultLoadEventListener {
/**
* serialVersionUID
*/
private static final long serialVersionUID = -3129774467686995363L;
/**
* HibernateのLoadイベントを呼び出す前に、
* 実体クラスのIDインスタンスをLoadイベントのIDインスタンスの代わりにする
*
* @param event Loadイベント
* @param loadType Load種別
* @throws HibernateException
*/
@Override
@SuppressWarnings(Constant.UNCHECKED)
public void onLoad(LoadEvent event, LoadEventListener.LoadType loadType) throws HibernateException {
// イベントの呼び出す元
final SessionImplementor source = event.getSession();
// 実体クラスを取得する
EntityPersister persister;
if (event.getInstanceToLoad() != null) {
persister = source.getEntityPersister(null, event.getInstanceToLoad());
//the load() which takes an entity does not pass an entityName
event.setEntityClassName(event.getInstanceToLoad().getClass().getName());
} else {
persister = source.getFactory().getEntityPersister(event.getEntityClassName());
}
if (persister == null) {
throw new HibernateException("Unable to locate persister: " + event.getEntityClassName());
}
// 実体クラスのIDクラス
final Class<Serializable> idClass = persister.getIdentifierType().getReturnedClass();
// LoadイベントのIDインスタンスが実体クラスではない場合、
// 実体クラスのIDインスタンスをLoadイベントのIDインスタンスの代わりにする
if (idClass != null && !idClass.isInstance(event.getEntityId())) {
Serializable id = null;
try {
// 実体クラスのIDクラスより、実体クラスのIDインスタンスを生成する
id = (Serializable) idClass.newInstance();
// LoadイベントのIDインスタンスより、、実体クラスに属性の値をコピーする
BeanUtils.copyProperties(event.getEntityId(), id);
} catch (Exception e) {
// 異常が発生する場合、異常の情報しかを出力しない
throw new TypeMismatchException(
"Provided id of the wrong type for class " + persister.getEntityName() + ". Expected: " + idClass
+ ", got " + event.getEntityId().getClass());
}
// 実体クラスのIDインスタンスをLoadイベントに設定する
event.setEntityId(id);
}
// HibernateのLoadイベントを呼び出す
super.onLoad(event, loadType);
}
最后注册事件:
@Component
public class MyEventListenerRegistry {
@Autowired
private SessionFactory sessionFactory;
/**
* イベントリスナーを登録する
*/
@PostConstruct
public void registerListeners() {
// イベントリスナーを管理するサービスを取得する
EventListenerRegistry serviceRegistry = ((SessionFactoryImpl) sessionFactory)
.getServiceRegistry().getService(EventListenerRegistry.class);
// Loadイベントのリスナーを登録する
serviceRegistry.prependListeners(EventType.LOAD, new EneresLoadEventListener());
}
}