diff --git a/README.md b/README.md index facdd2e..5f206b4 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ If you use Maven to manage your dependencies, Orianna Hibernate is posted on Mav com.robrua orianna-hibernate - 2.2.5 + 2.2.6 ``` diff --git a/pom.xml b/pom.xml index 610dd5f..088bd57 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 orianna-hibernate - 2.2.6-SNAPSHOT + 2.2.6 jar @@ -28,7 +28,7 @@ com.robrua orianna - 2.2.6-SNAPSHOT + 2.2.6 provided diff --git a/src/com/robrua/orianna/store/HibernateDB.java b/src/com/robrua/orianna/store/HibernateDB.java index 3066da9..674a6b4 100755 --- a/src/com/robrua/orianna/store/HibernateDB.java +++ b/src/com/robrua/orianna/store/HibernateDB.java @@ -8,6 +8,8 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; import org.hibernate.Criteria; import org.hibernate.ScrollMode; @@ -37,6 +39,7 @@ public static class Builder { private String dialect = "org.hibernate.dialect.MySQLDialect"; private String driver = "com.mysql.jdbc.Driver"; private int entityClearTheshold = 100; + private Level logLevel = Level.INFO; private String password = null; private boolean showSQL = false; private String url = null; @@ -65,6 +68,9 @@ public HibernateDB build() { throw new IllegalArgumentException("URL, Username, and Password must be set!"); } + final Logger logger = Logger.getLogger("org.hibernate"); + logger.setLevel(logLevel); + final Configuration configuration = new Configuration(); // DB configuration @@ -125,6 +131,16 @@ public Builder entityClearThreshold(final int entityClearTheshold) { return this; } + /** + * @param logLevel + * hibernate log level + * @return the builder + */ + public Builder logLevel(final Level logLevel) { + this.logLevel = logLevel; + return this; + } + /** * @param password * hibernate.connection.password @@ -167,9 +183,10 @@ public Builder username(final String username) { } private class DBIterator> extends CloseableIterator { + private final boolean hasAny; + private boolean isClosed = false; private final ScrollableResults result; private final Class type; - private final boolean hasAny; /** * @param type @@ -186,12 +203,23 @@ public DBIterator(final Class type, final ScrollableResults result) { @Override public void close() { - result.close(); + if(!isClosed) { + result.close(); + isClosed = true; + } } @Override public boolean hasNext() { - return hasAny && !result.isLast(); + if(isClosed) { + return false; + } + + final boolean hasNext = hasAny && !result.isLast(); + if(!hasNext && !isClosed) { + close(); + } + return hasNext; } @SuppressWarnings("unchecked") @@ -200,7 +228,7 @@ public T next() { if(!hasNext()) { return null; } - + result.next(); try { return (T)type.getDeclaredConstructors()[0].newInstance(result.get(0)); @@ -265,7 +293,7 @@ private static String getIndexRow(final Class clazz, final */ public HibernateDB(final Configuration cfg, final int entityClearTheshold) { this.entityClearTheshold = entityClearTheshold; - + // Add DTO classes cfg.addAnnotatedClass(com.robrua.orianna.type.dto.champion.Champion.class).addAnnotatedClass(com.robrua.orianna.type.dto.champion.ChampionList.class) .addAnnotatedClass(com.robrua.orianna.type.dto.currentgame.BannedChampion.class) diff --git a/src/com/robrua/orianna/store/SessionManager.java b/src/com/robrua/orianna/store/SessionManager.java index 49caf1f..8467476 100644 --- a/src/com/robrua/orianna/store/SessionManager.java +++ b/src/com/robrua/orianna/store/SessionManager.java @@ -8,85 +8,90 @@ import org.hibernate.SessionFactory; /** - * Handles multiple threads so that multiple threads can safely access the database. Automatically closes sessions from terminated threads. - * + * Handles multiple threads so that multiple threads can safely access the + * database. Automatically closes sessions from terminated threads. + * * @author Rob Rua (robrua@alumni.cmu.edu) */ public class SessionManager implements Closeable { - private final Map sessions; - private final SessionFactory factory; - private final long checkMillis; - private final Cleaner cleaner; - - /** - * @param factory the session factory - * @param checkMillis how often to check for terminated threads and close their sessions - */ - public SessionManager(SessionFactory factory, long checkMillis) { - this.factory = factory; - this.sessions = new ConcurrentHashMap<>(); - this.checkMillis = checkMillis; - this.cleaner = new Cleaner(); - new Thread(cleaner).start(); - } - - /** - * @return the hibernate session for the current thread - */ - public Session getSession() { - Thread thread = Thread.currentThread(); - Session session = sessions.get(thread); - if(session == null) { - session = factory.openSession(); - sessions.put(thread, session); - } - - return session; - } - - @Override - public void close() { - cleaner.stop(); - for(Session session : sessions.values()) { - session.close(); - } - factory.close(); - } - /** * Closes sessions from terminated threads */ - private class Cleaner implements Runnable { + private class Cleaner implements Runnable { private volatile boolean stopped = false; private Thread thread; - - /** - * Stops the cleaner - */ - public void stop() { - stopped = true; - thread.interrupt(); - } - + @Override public void run() { thread = Thread.currentThread(); - + while(!stopped) { - for(Thread thread : sessions.keySet()) { + for(final Thread thread : sessions.keySet()) { if(!thread.isAlive()) { sessions.get(thread).close(); sessions.remove(thread); } } - + try { Thread.sleep(checkMillis); } - catch(InterruptedException e) { + catch(final InterruptedException e) { continue; } } } + + /** + * Stops the cleaner + */ + public void stop() { + stopped = true; + thread.interrupt(); + } + } + + private final long checkMillis; + private final Cleaner cleaner; + private final SessionFactory factory; + + private final Map sessions; + + /** + * @param factory + * the session factory + * @param checkMillis + * how often to check for terminated threads and close their + * sessions + */ + public SessionManager(final SessionFactory factory, final long checkMillis) { + this.factory = factory; + sessions = new ConcurrentHashMap<>(); + this.checkMillis = checkMillis; + cleaner = new Cleaner(); + new Thread(cleaner).start(); + } + + @Override + public void close() { + cleaner.stop(); + for(final Session session : sessions.values()) { + session.close(); + } + factory.close(); + } + + /** + * @return the hibernate session for the current thread + */ + public Session getSession() { + final Thread thread = Thread.currentThread(); + Session session = sessions.get(thread); + if(session == null) { + session = factory.openSession(); + sessions.put(thread, session); + } + + return session; } }