package net.sf.jeasyorm; import java.lang.reflect.Constructor; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; public abstract class EntityManager { private static final Logger log = Logger.getLogger(EntityManager.class.getName()); private static Map<String, SqlInfo> infosByClassName = new HashMap<String, SqlInfo>(); private static List<Class<? extends EntityManager>> entityManagerClasses = new ArrayList<Class<? extends EntityManager>>(); static { register(BasicEntityManager.class); register(HSQLDBEntityManager.class); register(OracleEntityManager.class); register(PostgreSQLEntityManager.class); register(DerbyEntityManager.class); // MySQL (5.1) supported by BasicEntityManager // H2 supported by BasicEntityManager } private String cache; private Connection connection; private NameGuesser nameGuesser; public static EntityManager getInstance(Connection connection) { return getInstance(null, connection); } public static EntityManager getInstance(String cache, Connection connection) { for (Class<? extends EntityManager> emClass : entityManagerClasses) { try { Constructor<? extends EntityManager> c = emClass.getConstructor(Connection.class); EntityManager em = c.newInstance(connection); em.setCache(cache); return em; } catch (Exception e) { // ignore } } return null; } public static void clear() { infosByClassName.clear(); } @SuppressWarnings("unchecked") public static void register(String entityManagerClassName) { try { entityManagerClasses.add(0, (Class<? extends EntityManager>) Class.forName(entityManagerClassName)); } catch (Exception e) { throw new RuntimeException("Class '" + entityManagerClassName + "' not found!"); } } public static void register(Class<? extends EntityManager> entityManagerClass) { entityManagerClasses.add(0, entityManagerClass); } protected static SqlInfo getSqlInfo(EntityManager manager, Class<?> entityClass) { String key = (manager.getCache() != null ? manager.getCache() + ":" : "") + entityClass.getName(); SqlInfo info = infosByClassName.get(key); if (info == null && !infosByClassName.containsKey(key)) { info = manager.newSqlInfo(entityClass); infosByClassName.put(key, info); } return info; } /** * Constructors of child classes should throw an exception if they do not * support the database type of the connection. * (e.g. by checking connection.getMetaData().getDatabaseProductName()) */ protected EntityManager(Connection connection) { this.connection = connection; } public Connection getConnection() { return connection; } public String getCache() { return cache; } public void setCache(String cache) { this.cache = cache; } public NameGuesser getNameGuesser() { if (nameGuesser == null) nameGuesser = new SimpleNameGuesser(); return nameGuesser; } public void setNameGuesser(NameGuesser nameGuesser) { this.nameGuesser = nameGuesser; } protected abstract SqlInfo newSqlInfo(Class<?> entityClass); protected Mapping newMapping(Class<?> entityClass) throws SQLException { return new Mapping(this, entityClass); } public abstract <T> T load(Class<T> entityClass, Object... pk); public abstract <T> T findUnique(Class<T> entityClass, String query, Object... params); public abstract <T> List<T> find(Class<T> entityClass, String query, Object... params); public abstract <T> Page<T> find(Class<T> entityClass, int pageNum, int pageSize, String query, Object... params); public abstract <T> Iterator<T> iterator(Class<T> entityClass, String query, Object... params); public abstract int count(String query, Object... params); public abstract <T> T insert(T entity); public abstract <T> void update(T entity); public abstract <T> void delete(T entity); protected void log(Level level, String message, Object... params) { log.log(level, message, params); } protected void log(Level level, String message, Throwable t) { log.log(level, message, t); } protected static class SqlInfo { protected Mapping mapping; protected String loadSql; protected String selectSql; protected String insertSql; protected String updateSql; protected String deleteSql; protected SqlInfo(Mapping mapping) { this.mapping = mapping; } } }