/* * Copyright 2012 Christopher Pheby * * 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 org.jadira.usertype.spi.repository; import java.io.Serializable; import javax.persistence.LockModeType; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.jpa.HibernateEntityManagerFactory; import org.hibernate.metadata.ClassMetadata; import org.jadira.usertype.spi.utils.reflection.TypeHelper; /** * Base implementation of a Repository / type-safe DAO using Hibernate JPA * * @param <T> Entity type that this Repository handles * @param <ID> The type that identifies the ID column for the supported entity type */ public abstract class JpaBaseRepository<T extends Serializable, ID extends Serializable> extends JpaSearchRepository<T, ID> implements BaseRepository<T, ID> { protected JpaBaseRepository() { } /** * Determines the ID for the entity * * @param entity The entity to retrieve the ID for * @return The ID */ @SuppressWarnings("deprecation") // No good alternative in the Hibernate API yet protected ID extractId(T entity) { final Class<?> entityClass = TypeHelper.getTypeArguments(JpaBaseRepository.class, this.getClass()).get(0); final SessionFactory sf = ((HibernateEntityManagerFactory) getEntityManager().getEntityManagerFactory()).getSessionFactory(); final ClassMetadata cmd = sf.getClassMetadata(entityClass); final SessionImplementor si = (SessionImplementor)(getEntityManager().getDelegate()); @SuppressWarnings("unchecked") final ID result = (ID) cmd.getIdentifier(entity, si); return result; } /** * {@inheritDoc} */ @Override public T persist(T entity) { // Case of new, non-persisted entity if (extractId(entity) == null) { getEntityManager().persist(entity); } else if (!getEntityManager().contains(entity)) { // In the case of an attached entity, we do nothing (it // will be persisted automatically on synchronisation) // But... in the case of an unattached, but persisted entity // we perform a merge to re-attach and persist it entity = getEntityManager().merge(entity); } return entity; } /** * {@inheritDoc} */ @Override public void remove(ID entityId) { T entity = getEntityManager().find(getEntityClass(), entityId); // Case of attached entity - simply remove it if (getEntityManager().contains(entity)) { getEntityManager().remove(entity); } // Case of unattached entity, first it is necessary to perform // a merge, before doing the remove else { entity = getEntityManager().merge(entity); getEntityManager().remove(entity); } } /** * {@inheritDoc} */ @Override public T refresh(T entity) { // Attempting to refresh a non-persisted entity // will result in an exception if (extractId(entity) == null) { // causes exception getEntityManager().refresh(entity); } // Case of attached empty - this gets refreshed else if (getEntityManager().contains(entity)) { getEntityManager().refresh(entity); } // Case of unattached entity, first it is necessary to perform // a merge, before doing the refresh else { entity = getEntityManager().merge(entity); getEntityManager().refresh(entity); } return entity; } /** * {@inheritDoc} */ @Override public T evict(T entity) { Session session = (Session) getEntityManager().getDelegate(); session.evict(entity); return entity; } /** * {@inheritDoc} */ @Override public void flush() { getEntityManager().flush(); } /** * {@inheritDoc} */ @Override public void lock(T entity, LockModeType lockMode) { getEntityManager().lock(entity, lockMode); } }