final String dataSource = Yalp.configuration.getProperty("hibernate.connection.datasource");
if (StringUtils.isEmpty(dataSource) && DB.datasource == null) {
throw new JPAException("Cannot start a JPA manager without a properly configured database", new NullPointerException("No datasource configured"));
}
Ejb3Configuration cfg = new Ejb3Configuration();
if (DB.datasource != null) {
cfg.setDataSource(DB.datasource);
}
if (!Yalp.configuration.getProperty("jpa.ddl", Yalp.mode.isDev() ? "update" : "none").equals("none")) {
cfg.setProperty("hibernate.hbm2ddl.auto", Yalp.configuration.getProperty("jpa.ddl", "update"));
}
cfg.setProperty("hibernate.dialect", getDefaultDialect(Yalp.configuration.getProperty("db.driver")));
cfg.setProperty("javax.persistence.transaction", "RESOURCE_LOCAL");
// Explicit SAVE for JPABase is implemented here
// ~~~~~~
// We've hacked the org.hibernate.event.def.AbstractFlushingEventListener line 271, to flush collection update,remove,recreation
// only if the owner will be saved or if the targeted entity will be saved (avoid the org.hibernate.HibernateException: Found two representations of same collection)
// As is:
// if (session.getInterceptor().onCollectionUpdate(coll, ce.getLoadedKey())) {
// actionQueue.addAction(...);
// }
//
// This is really hacky. We should move to something better than Hibernate like EBEAN
cfg.setInterceptor(new EmptyInterceptor() {
@Override
public int[] findDirty(Object o, Serializable id, Object[] arg2, Object[] arg3, String[] arg4, Type[] arg5) {
if (o instanceof JPABase && !((JPABase) o).willBeSaved) {
return new int[0];
}
return null;
}
@Override
public boolean onCollectionUpdate(Object collection, Serializable key) throws CallbackException {
if (collection instanceof PersistentCollection) {
Object o = ((PersistentCollection) collection).getOwner();
if (o instanceof JPABase) {
if (entities.get() != null) {
return ((JPABase) o).willBeSaved || ((JPABase) entities.get()).willBeSaved;
} else {
return ((JPABase) o).willBeSaved;
}
}
} else {
System.out.println("HOO: Case not handled !!!");
}
return super.onCollectionUpdate(collection, key);
}
@Override
public boolean onCollectionRecreate(Object collection, Serializable key) throws CallbackException {
if (collection instanceof PersistentCollection) {
Object o = ((PersistentCollection) collection).getOwner();
if (o instanceof JPABase) {
if (entities.get() != null) {
return ((JPABase) o).willBeSaved || ((JPABase) entities.get()).willBeSaved;
} else {
return ((JPABase) o).willBeSaved;
}
}
} else {
System.out.println("HOO: Case not handled !!!");
}
return super.onCollectionRecreate(collection, key);
}
@Override
public boolean onCollectionRemove(Object collection, Serializable key) throws CallbackException {
if (collection instanceof PersistentCollection) {
Object o = ((PersistentCollection) collection).getOwner();
if (o instanceof JPABase) {
if (entities.get() != null) {
return ((JPABase) o).willBeSaved || ((JPABase) entities.get()).willBeSaved;
} else {
return ((JPABase) o).willBeSaved;
}
}
} else {
System.out.println("HOO: Case not handled !!!");
}
return super.onCollectionRemove(collection, key);
}
protected ThreadLocal<Object> entities = new ThreadLocal<Object>();
@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
entities.set(entity);
return super.onSave(entity, id, state, propertyNames, types);
}
@Override
public void afterTransactionCompletion(org.hibernate.Transaction tx) {
entities.remove();
}
});
if (Yalp.configuration.getProperty("jpa.debugSQL", "false").equals("true")) {
org.apache.log4j.Logger.getLogger("org.hibernate.SQL").setLevel(Level.ALL);
} else {
org.apache.log4j.Logger.getLogger("org.hibernate.SQL").setLevel(Level.OFF);
}
// inject additional hibernate.* settings declared in Yalp configuration
cfg.addProperties((Properties) Utils.Maps.filterMap(Yalp.configuration, "^hibernate\\..*"));
try {
Field field = cfg.getClass().getDeclaredField("overridenClassLoader");
field.setAccessible(true);
field.set(cfg, Yalp.classloader);
} catch (Exception e) {
Logger.error(e, "Error trying to override the hibernate classLoader (new hibernate version ???)");
}
for (Class<?> clazz : classes) {
if (clazz.isAnnotationPresent(Entity.class)) {
cfg.addAnnotatedClass(clazz);
if (Logger.isTraceEnabled()) {
Logger.trace("JPA Model : %s", clazz);
}
}
}
String[] moreEntities = Yalp.configuration.getProperty("jpa.entities", "").split(", ");
for (String entity : moreEntities) {
if (entity.trim().equals("")) {
continue;
}
try {
cfg.addAnnotatedClass(Yalp.classloader.loadClass(entity));
} catch (Exception e) {
Logger.warn("JPA -> Entity not found: %s", entity);
}
}
for (ApplicationClass applicationClass : Yalp.classes.all()) {
if (applicationClass.isClass() || applicationClass.javaPackage == null) {
continue;
}
Package p = applicationClass.javaPackage;
Logger.info("JPA -> Adding package: %s", p.getName());
cfg.addPackage(p.getName());
}
String mappingFile = Yalp.configuration.getProperty("jpa.mapping-file", "");
if (mappingFile != null && mappingFile.length() > 0) {
cfg.addResource(mappingFile);
}
if (Logger.isTraceEnabled()) {
Logger.trace("Initializing JPA ...");
}
try {
JPA.entityManagerFactory = cfg.buildEntityManagerFactory();
} catch (PersistenceException e) {
throw new JPAException(e.getMessage(), e.getCause() != null ? e.getCause() : e);
}
JPQL.instance = new JPQL();
}