net.commerce.zocalo.hibernate.HibernateUtil.java Source code

Java tutorial

Introduction

Here is the source code for net.commerce.zocalo.hibernate.HibernateUtil.java

Source

package net.commerce.zocalo.hibernate;

import net.commerce.zocalo.claim.BinaryClaim;
import net.commerce.zocalo.claim.Claim;
import net.commerce.zocalo.currency.CashBank;
import net.commerce.zocalo.currency.CurrencyToken;
import net.commerce.zocalo.market.*;
import net.commerce.zocalo.user.SecureUser;
import net.commerce.zocalo.user.UnconfirmedUser;
import net.commerce.zocalo.user.User;
import org.apache.log4j.Logger;
import org.hibernate.*;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Order;

import java.sql.*;
import java.util.List;
import java.util.Iterator;

// Copyright 2007-2009 Chris Hibbert.  All rights reserved.
// Copyright 2006 CommerceNet Consortium, LLC.  All rights reserved.

// This software is published under the terms of the MIT license, a copy
// of which has been included with this distribution in the LICENSE file.

/**
Utilities for dealing with Hibernate.  Everything from general tools for creating and
managing connections to specific queries of general use.
 */

public class HibernateUtil {
    protected static SessionFactory sessionFactory = new NoDBSessionFactory();;
    protected static final ThreadLocal sessionHolder = new ThreadLocal();
    static public final String SCHEMA_CREATE = "create";
    static public final String SCHEMA_CREATE_DROP = "create-drop";
    static public final String SCHEMA_UPDATE = "update";

    static public void initializeSessionFactory(String connectionURL, String schemaCreateMode) {
        if (sessionFactory != null && !(sessionFactory instanceof NoDBSessionFactory)) {
            return;
        }
        try {
            Configuration cfg = new Configuration();
            addClasses(cfg);
            if (connectionURL != null && !"".equals(connectionURL)) {
                cfg.setProperty("hibernate.connection.url", connectionURL);
            }
            cfg.setProperty("hibernate.hbm2ddl.auto", schemaCreateMode);

            sessionFactory = cfg.buildSessionFactory();
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed: " + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    static public String connectionUrl(String dbFilePath, boolean create) {
        // edit hibernate.properties when you switch this
        return hsqlFileUrl(dbFilePath);
        //        return derbyUrl(dbFilePath, create);
    }

    static public String derbyUrl(String dbFilePath, boolean create) {
        return "jdbc:derby:" + dbFilePath + (create ? ";create=true" : "");
    }

    static public String hsqlFileUrl(String dbFilePath) {
        return "jdbc:hsqldb:file:" + dbFilePath;
    }

    public static Session currentSession() throws HibernateException {
        Session s = (Session) sessionHolder.get();
        if (sessionFactory != null) {
            if (s == null || !s.isOpen()) {
                s = sessionFactory.openSession();
                sessionHolder.set(s);
            }
        }
        return s;
    }

    public static void closeSession() throws HibernateException {
        Session s = (Session) sessionHolder.get();
        if (s != null)
            s.close();
        sessionHolder.set(null);
    }

    static void addClasses(Configuration configuration) {
        configuration.addClass(net.commerce.zocalo.claim.Claim.class);
        configuration.addClass(net.commerce.zocalo.claim.Position.class);
        configuration.addClass(net.commerce.zocalo.currency.CurrencyToken.class);
        configuration.addClass(net.commerce.zocalo.currency.Coupons.class);
        configuration.addClass(net.commerce.zocalo.currency.CashBank.class);
        configuration.addClass(net.commerce.zocalo.currency.CouponBank.class);
        configuration.addClass(net.commerce.zocalo.currency.Funds.class);
        //        configuration.addClass(net.commerce.zocalo.currency.Currency.class); // Using Table-per-concrete-subclass for Currency/Funds/Coupons
        configuration.addClass(net.commerce.zocalo.currency.Accounts.class);
        configuration.addClass(net.commerce.zocalo.orders.Order.class);
        configuration.addClass(net.commerce.zocalo.orders.SortedOrders.class);
        configuration.addClass(net.commerce.zocalo.user.SecureUser.class);
        configuration.addClass(net.commerce.zocalo.user.UnconfirmedUser.class);
        configuration.addClass(net.commerce.zocalo.market.Market.class);
        configuration.addClass(net.commerce.zocalo.market.MarketMaker.class);
        configuration.addClass(net.commerce.zocalo.market.Book.class);
        configuration.addClass(net.commerce.zocalo.market.Outcome.class);
        configuration.addClass(net.commerce.zocalo.ajax.events.Ask.class);
        configuration.addClass(net.commerce.zocalo.ajax.events.Bid.class);
        configuration.addClass(net.commerce.zocalo.ajax.events.BestAsk.class);
        configuration.addClass(net.commerce.zocalo.ajax.events.BestBid.class);
        configuration.addClass(net.commerce.zocalo.ajax.events.Trade.class); // using table-per-hierarchy for BookTrade/MakerTrade
        configuration.addClass(net.commerce.zocalo.ajax.events.SelfDealing.class);
        configuration.addClass(net.commerce.zocalo.ajax.events.OrderRemoval.class);
        configuration.addClass(net.commerce.zocalo.ajax.events.Redemption.class);
        //        configuration.addClass(net.commerce.zocalo.currency.Quantity.class);        // Always a component
        //        configuration.addClass(net.commerce.zocalo.currency.Probability.class);     // Always a component
        //        configuration.addClass(net.commerce.zocalo.currency.Price.class);           // Always a component
    }

    public static void save(Object o) {
        Session session = currentSession();
        if (session != null) {
            session.save(o);
        }
    }

    public static void delete(Object o) {
        Session session = currentSession();
        if (session != null) {
            session.delete(o);
        }
    }

    static public CashBank getOrMakePersistentRootBank(String rootCashBankName) throws HibernateException {
        CashBank result;
        Session session = currentSession();
        Criteria tokenCriterion = session.createCriteria(CurrencyToken.class);
        tokenCriterion.add(Expression.eq("name", rootCashBankName));
        List tokens = tokenCriterion.list();
        if (tokens.size() > 1) {
            throw new HibernateException("too many root banks");
        } else if (tokens.size() == 1) {
            CurrencyToken t = (CurrencyToken) tokens.get(0);
            result = t.lookupCashBank(session);
        } else {
            result = new CashBank(rootCashBankName);
            session.save(result);
        }
        return result;
    }

    public static SecureUser getUserByName(String name) {
        return getUserByName(name, currentSession());
    }

    public static SecureUser getUserByName(String name, Session session) {
        Criteria userCriterion = session.createCriteria(SecureUser.class);
        userCriterion.add(Expression.eq("name", name));
        userCriterion.setCacheable(true);
        return (SecureUser) userCriterion.uniqueResult();
    }

    public static UnconfirmedUser getUnconfirmedUserByName(String name, Session session) {
        Criteria userCriterion = session.createCriteria(UnconfirmedUser.class);
        userCriterion.add(Expression.eq("name", name));
        return (UnconfirmedUser) userCriterion.uniqueResult();
    }

    public static void removeUnconfirmedUserByName(String name, Session session) {
        Criteria userCriterion = session.createCriteria(UnconfirmedUser.class);
        userCriterion.add(Expression.eq("name", name));
        UnconfirmedUser user = (UnconfirmedUser) userCriterion.uniqueResult();
        session.delete(user);
        return;
    }

    public static boolean marketsExist() {
        Criteria marketCriterion = currentSession().createCriteria(Market.class);
        marketCriterion.setMaxResults(1);
        return marketCriterion.list().size() > 0;
    }

    public static List allOpenBinaryMarkets() {
        Criteria marketCriterion = currentSession().createCriteria(BinaryMarket.class);
        marketCriterion.add(Expression.eq("marketClosed", Boolean.FALSE));
        marketCriterion.setCacheable(true);
        return marketCriterion.list();
    }

    public static List allOpenMultiMarkets() {
        Criteria marketCriterion = currentSession().createCriteria(MultiMarket.class);
        marketCriterion.add(Expression.eq("marketClosed", Boolean.FALSE));
        marketCriterion.setCacheable(true);
        return marketCriterion.list();
    }

    public static List allClosedMarkets() {
        Criteria marketCriterion = currentSession().createCriteria(Market.class);
        marketCriterion.add(Expression.eq("marketClosed", Boolean.TRUE));
        marketCriterion.addOrder(Order.desc("id")); // we don't have the time of closure
        marketCriterion.setCacheable(true);
        return marketCriterion.list();
    }

    public static List tradeListForJsp(String claimName) {
        Claim claim = getClaimByName(claimName);
        Session session = currentSession();
        Query mQ = session.createQuery("select t from Trade t " + "join t.pos p "
                + "where t.pos = p.id and p.claim = :cl " + "order by t.time");
        mQ.setEntity("cl", claim);
        mQ.setCacheable(true);
        return mQ.list();
    }

    public static List maxTradeTime(String claimName) {
        Claim claim = getClaimByName(claimName);
        Session session = currentSession();
        Query mQ = session.createQuery(
                "select max(t.time) from Trade t " + "join t.pos p " + "where t.pos = p.id and p.claim = :cl ");
        mQ.setEntity("cl", claim);
        mQ.setCacheable(true);
        return mQ.list();
    }

    public static Market getMarketByName(String name) {
        Session session = currentSession();
        Query mQ = session.createQuery(
                "select m from Market m " + "join m.claim c " + "where m.claim = c.id and c.name = :name");
        mQ.setString("name", name);
        mQ.setCacheable(true);
        return (Market) mQ.uniqueResult();
    }

    public static MultiMarket getMultiMarketByName(String name) {
        Session session = currentSession();
        Query mQ = session.createQuery(
                "select m from MultiMarket m " + "join m.claim c " + "where m.claim = c.id and c.name = :name");
        mQ.setString("name", name);
        mQ.setCacheable(true);
        return (MultiMarket) mQ.uniqueResult();
    }

    public static BinaryClaim getBinaryClaimByName(String name) {
        Session session = HibernateUtil.currentSession();
        Criteria claimCriterion = session.createCriteria(BinaryClaim.class);
        claimCriterion.add(Expression.eq("name", name));
        claimCriterion.setCacheable(true);
        return (BinaryClaim) claimCriterion.uniqueResult();
    }

    public static Claim getClaimByName(String name) {
        Session session = HibernateUtil.currentSession();
        Criteria claimCriterion = session.createCriteria(Claim.class);
        claimCriterion.add(Expression.eq("name", name));
        claimCriterion.setCacheable(true);
        return (Claim) claimCriterion.uniqueResult();
    }

    public static List couponOwners(Claim claim) {
        Session session = currentSession();

        //TODO: I can't see how to access the Claims that are the keys of acct's positions map.
        //TODO: that would require two fewer joins!
        //select  owner.user_id" +
        //from public.USER owner, public.accounts acct, PUBLIC.ACCOUNT_HOLDINGS assets, PUBLIC.POSITIONS pos " +
        //  where  owner.accounts = acct.accounts_id" +
        //         and acct.accounts_id = assets.accounts_id"
        //         and assets.POSITIONS_ID = pos.positions_id " +
        //         and pos.claims_ID=2 " +

        Query qa = session.createQuery("select u \n" + "from SecureUser u \n" + "   join u.accounts acct\n"
                + "   join acct.positions coupon  \n"
                + "where u.accounts = acct.id and coupon.position.claim = :claim ");
        qa.setEntity("claim", claim);
        qa.setCacheable(true);
        return qa.list();
    }

    public static void refresh(Object o) {
        currentSession().refresh(o);
    }

    public static Transaction beginTransactionForJsp() {
        Session session = currentSession();
        return session.beginTransaction();
    }

    public static List getOrdersForUser(User user) {
        Query query = currentSession().createQuery(
                "select o from Order o " + "join o.owner u " + "where o.owner = u.id and u.name = :name");
        query.setString("name", user.getName());
        query.setCacheable(true);
        return query.list();
    }

    static public List getTrades(SecureUser user) {
        Query query = currentSession().createQuery("select t from Trade t " + "join t.pos p " + "join p.claim cl "
                + "where t.pos = p.id and t.owner = :name " + "order by cl.id, t.time");
        query.setString("name", user.getName());
        query.setCacheable(true);
        return query.list();
    }

    public static List getTrades(SecureUser user, Market market) {
        Query query = currentSession().createQuery("select t from Trade t " + "join t.pos p " + "join p.claim cl "
                + "where t.pos = p.id and t.owner = :name and cl.name = :claimName " + "order by t.time desc");
        query.setString("name", user.getName());
        query.setString("claimName", market.getName());
        query.setCacheable(true);
        return query.list();
    }

    public static List getRedemptions(SecureUser user, Market market) {
        Query query = currentSession().createQuery("select r from Redemption r " + "join r.pos p "
                + "join p.claim cl " + "where r.pos = p.id and r.owner = :name and cl.name = :claimName ");
        query.setString("name", user.getName());
        query.setCacheable(true);
        query.setString("claimName", market.getName());
        query.setCacheable(true);
        return query.list();
    }

    static public void shutdown(String connectionURL) throws SQLException {
        Connection con = DriverManager.getConnection(connectionURL, "sa", "");
        con.createStatement().execute("SHUTDOWN");
        Logger.getLogger(HibernateUtil.class).warn("Hibernate session has been closed");
    }

    /** Upgrade Database to format for 2007.5; Markets store their owners directly. */
    static public void updateDB2007_5(String connectionURL) throws SQLException {
        Connection con = DriverManager.getConnection(connectionURL, "sa", "");
        Statement prepped = con.createStatement();
        prepped.executeUpdate("update PUBLIC.MARKET set market.owner = "
                + "(select claims.owner from public.claims where claims.claims_id = market.claim)");
        return;
    }

    /** See if Database has been upgraded to format for 2007.5;
        afterwards Markets store their owners directly. */
    public static List getUnowedMarket() {
        Session session = currentSession();
        Query mQ = session.createQuery("select m from Market m where m.owner is null");
        return mQ.list();
    }

    /** See if Database has been upgraded to format for 2008.3;
        afterwards MarketMakers store their Beta. */
    public static List getMakerWithoutBeta() {
        Session session = currentSession();
        Query mQ = session.createQuery("select mm from MarketMaker mm where mm.beta.quant is null");
        return mQ.list();
    }

    /** see if database has been upgraded for 2008.4.  Markets now represent
     * their outcome.  */
    public static List getMarketsSansOutcome() {
        Session session = currentSession();
        Query mQ = session.createQuery("select m from Market m where m.outcome is null");
        return mQ.list();
    }

    /** see if database has been upgraded for 2009.1.  Positions are now ordered.  */
    public static void getPositionSansIndex() {
        List listB = allOpenBinaryMarkets();
        for (Iterator iterator = listB.iterator(); iterator.hasNext();) {
            BinaryMarket market = (BinaryMarket) iterator.next();
            market.getClaim().positions();
        }
        List listM = allOpenMultiMarkets();
        for (Iterator iterator = listM.iterator(); iterator.hasNext();) {
            MultiMarket market = (MultiMarket) iterator.next();
            market.getClaim().positions();
        }
    }

    /** Upgrade Database to format for 2008.3; MarketMakers store Beta, not subsidy.  This method
       sets all Betas to a single (barely) plausible value.  There's a shell script (and python)
     program that uses sqlTool to do a better job.  */
    static public void updateDB2008_3(String connectionURL) throws SQLException {
        Connection con = DriverManager.getConnection(connectionURL, "sa", "");

        Session session = currentSession();
        Query query = session.createQuery("select c from Claim c");
        List claims = query.list();

        Query confirmation = currentSession().createQuery(
                "select mm.beta " + "from MarketMaker mm \n" + "        join mm.market m" + "        join m.claim c"
                        + "     where mm.market = m \n" + "     and m.claim = c \n" + "     and c.name = :name");

        for (Iterator it = claims.iterator(); it.hasNext();) {
            Claim claim = (Claim) it.next();

            confirmation.setString("name", claim.getName());
            if ((confirmation.uniqueResult() == null)) {
                Statement update = con.createStatement();
                double newBeta = 100.0 / Math.log(3);
                try {
                    update.executeUpdate("update MarketMaker set MarketMaker.beta = " + newBeta);

                    confirmation.setString("name", claim.getName());
                    if (newBeta != ((Double) confirmation.uniqueResult()).doubleValue()) {
                        throw new RuntimeException("didn't update beta for " + claim.getName());
                    }
                    break;
                } catch (SQLException e) {
                    e.printStackTrace();
                } catch (RuntimeException e) {
                    e.printStackTrace();
                }
            } else {
                break;
            }
        }
    }

    public static void updateDB2008_4(String dbFileURL) {
        Session session = currentSession();
        Transaction transaction = session.beginTransaction();

        Outcome open = Outcome.newOpen(false);
        session.save(open);
        List markets = HibernateUtil.getMarketsSansOutcome();
        for (Iterator iterator = markets.iterator(); iterator.hasNext();) {
            Market market = (Market) iterator.next();
            market.setOutcome(open);
        }
        transaction.commit();
    }

    public static boolean isStatisticsEnabled() {
        return currentSession().getSessionFactory().getStatistics().isStatisticsEnabled();
    }
}