/*
* Copyright 2013- Yan Bonnel
*
* 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 fr.ybonnel.simpleweb4j.model;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
/**
* Simple entityManager from SimpleWeb4j.
* Use :
* {@code SimpleEntityManager<Computer, Long> simpleEntityManager = new SimpleEntityManager<>(Computer.class);
* }
* @param <T> The entity to manage.
* @param <I> The id type.
*/
public class SimpleEntityManager<T, I extends Serializable> {
/**
* Class of the entity.
*/
private Class<T> entityClass;
/**
* Constructor.
* @param entityClass class of entity.
*/
public SimpleEntityManager(Class<T> entityClass) {
this.entityClass = entityClass;
}
/**
* Path to hibernate config file.
*/
private static String cfgPath = "fr/ybonnel/simpleweb4j/model/hibernate.cfg.xml";
/**
* Change the path to hibernate config file.
* @param newCfgPath new path to hibernate config file.
*/
public static void setCfgPath(String newCfgPath) {
cfgPath = newCfgPath;
}
/**
* List of entities.
*/
private static Collection<Class<?>> entitiesClasses = null;
/**
* Change the list of entities classes.
* @param newEntitiesClasses new list of entities classes.
*/
public static void setEntitiesClasses(Collection<Class<?>> newEntitiesClasses) {
entitiesClasses = newEntitiesClasses;
}
/**
* Method used to know if the current application have entities to manage.
* @return true is there's entities to manage.
*/
public static boolean hasEntities() {
return !getAnnotatedClasses().isEmpty();
}
/**
* Helper to have lazy initialize of SessionFactory.
*/
private static class SessionFactoryHelper {
/**
* Session factory.
*/
//CHECKSTYLE:OFF
public static SessionFactory sessionFactory = init();
//CHECKSTYLE:ON
/**
* Initialize of Session factory.
* @return the session factory initialized.
*/
private static SessionFactory init() {
Configuration configuration = new Configuration();
configuration.configure(cfgPath);
for (Class<?> entityClass : getAnnotatedClasses()) {
configuration.addAnnotatedClass(entityClass);
}
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(
configuration.getProperties()).buildServiceRegistry();
return configuration.buildSessionFactory(serviceRegistry);
}
/**
* Reset the session factory, used for tests.
*/
protected static void reset() {
sessionFactory = init();
}
}
/**
* Save state of annotated classes to allow changes for tests.
*/
private static Collection<Class<?>> oldAnnotatedClasses = null;
/**
* Get the session factory.
* @return session factory.
*/
protected static SessionFactory getSessionFactory() {
if (oldAnnotatedClasses != null
&& oldAnnotatedClasses != getAnnotatedClasses()
&& !Arrays.equals(oldAnnotatedClasses.toArray(), getAnnotatedClasses().toArray())) {
SessionFactoryHelper.reset();
}
oldAnnotatedClasses = getAnnotatedClasses();
return SessionFactoryHelper.sessionFactory;
}
/**
* Opened sessions.
*/
private static ThreadLocal<Session> currentSessions = new ThreadLocal<>();
/**
* Open a session (don't use it directly, the session is automatically open by SimpleWeb4j).
* @return the opened session.
*/
public static Session openSession() {
if (getCurrentSession() != null) {
throw new IllegalStateException("There is already a session for the current thread");
}
Session session = getSessionFactory().openSession();
currentSessions.set(session);
return session;
}
/**
* Close the current session (don't use it directly, the session is automatically close by SimpleWeb4j).
*/
public static void closeSession() {
Session session = currentSessions.get();
if (session == null) {
throw new IllegalStateException("There is no session for the current thread");
}
session.close();
currentSessions.remove();
}
/**
* Get the current session.
* @return the current session.
*/
public static Session getCurrentSession() {
return currentSessions.get();
}
/**
* Get the annotated classes (entities).
*
* @return the list of annotated classes.
*/
private static Collection<Class<?>> getAnnotatedClasses() {
if (entitiesClasses == null) {
entitiesClasses = new ArrayList<>();
}
return entitiesClasses;
}
/**
* Save an entity.
* @param entity the entity to save.
*/
public void save(T entity) {
getCurrentSession().save(entity);
}
/**
* Update an entity.
* @param entity entity to update.
*/
public void update(T entity) {
getCurrentSession().update(entity);
}
/**
* Get an entity by the id.
* @param id id of the entity.
* @return the entity if found, null otherwise.
*/
@SuppressWarnings("unchecked")
public T getById(I id) {
return (T) getCurrentSession().get(entityClass, id);
}
/**
* Get all entities.
* @return the list of all entities.
*/
@SuppressWarnings("unchecked")
public Collection<T> getAll() {
return getCurrentSession().createCriteria(entityClass).list();
}
/**
* Delete an entity.
* @param id id of the entity.
*/
public void delete(I id) {
getCurrentSession().delete(getCurrentSession().get(entityClass, id));
}
}