Java tutorial
/** * Copyright 2010 Molindo GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package at.molindo.esi4j.module.hibernate; import java.io.Serializable; import java.util.Date; import java.util.Map.Entry; import org.hibernate.CacheMode; import org.hibernate.FlushMode; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.internal.SessionImpl; import org.hibernate.metadata.ClassMetadata; import at.molindo.esi4j.chain.Esi4JEntityResolver; import at.molindo.utils.collections.ClassMap; public class HibernateEntityResolver implements Esi4JEntityResolver { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(HibernateEntityResolver.class); private final SessionFactory _sessionFactory; private final ClassMap<String> _entityNames = ClassMap.create(); private final ThreadLocal<Session> _localSession = new ThreadLocal<Session>(); public HibernateEntityResolver(SessionFactory sessionFactory) { if (sessionFactory == null) { throw new NullPointerException("sessionFactory"); } for (Entry<String, ClassMetadata> e : sessionFactory.getAllClassMetadata().entrySet()) { Class<?> mappedClass = e.getValue().getMappedClass(); if (mappedClass != null) { _entityNames.put(mappedClass, e.getKey()); } } _sessionFactory = sessionFactory; } /** * must be called within originating session */ @Override public ObjectKey toObjectKey(Object entity) { SessionFactory factory = getSessionFactory(); Session session = getCurrentSession(factory); String entityName = _entityNames.find(entity.getClass()); ClassMetadata meta = factory.getClassMetadata(entityName); Class<?> type = meta.getMappedClass(); Serializable id = meta.getIdentifier(entity, (SessionImpl) session); Long version = toLongVersion(meta.getVersion(entity)); return new ObjectKey(type, id, version); } private Long toLongVersion(Object version) { if (version instanceof Number) { return ((Number) version).longValue(); } else if (version instanceof Date) { return ((Date) version).getTime(); } else if (version != null) { log.warn("unexpected version type " + version.getClass().getName()); } return null; } /** * must be called within originating session */ @Override public Object replaceEntity(Object entity) { return toObjectKey(entity); } public void openResolveSession() { Session session = _localSession.get(); if (session != null) { log.warn("session already open, now closing first"); closeResolveSession(); session = null; } session = getNewSession(getSessionFactory()); session.setDefaultReadOnly(true); session.setCacheMode(CacheMode.GET); session.setFlushMode(FlushMode.MANUAL); session.beginTransaction(); _localSession.set(session); } public void closeResolveSession() { Session session = _localSession.get(); if (session != null) { session.getTransaction().commit(); session.clear(); session.close(); _localSession.set(null); } else { log.warn("session not open"); } } @Override public Object resolveEntity(Object replacedEntity) { if (replacedEntity instanceof ObjectKey) { ObjectKey key = (ObjectKey) replacedEntity; Session session = _localSession.get(); if (session == null) { throw new IllegalStateException("no session available"); } // ignore version, use latest, use load for batch fetching Object resolvedEntity = session.load(key.getType(), key.getId()); if (resolvedEntity == null) { log.error("can't resolve object " + key); return null; } return resolvedEntity; } else { // not replaced return replacedEntity; } } protected Session getCurrentSession(SessionFactory factory) { return factory.getCurrentSession(); } protected Session getNewSession(SessionFactory factory) { return factory.openSession(); } public final SessionFactory getSessionFactory() { return _sessionFactory; } }