r1916 - trunk/topia-persistence/src/main/java/org/nuiton/topia/framework
Author: fdesbois Date: 2010-04-29 21:21:12 +0200 (Thu, 29 Apr 2010) New Revision: 1916 Url: http://nuiton.org/repositories/revision/topia/1916 Log: Ano #560 : add distinct case for topiaQuery executeCount + clean some javadoc and reformat for 80chars Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaQuery.java Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaQuery.java =================================================================== --- trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaQuery.java 2010-04-29 05:57:59 UTC (rev 1915) +++ trunk/topia-persistence/src/main/java/org/nuiton/topia/framework/TopiaQuery.java 2010-04-29 19:21:12 UTC (rev 1916) @@ -318,7 +318,8 @@ * @param mainEntityClass * @param alias for the mainEntityClass */ - public TopiaQuery(Class<? extends TopiaEntity> mainEntityClass, String alias) { + public TopiaQuery(Class<? extends TopiaEntity> mainEntityClass, + String alias) { this(); setFrom(mainEntityClass, alias); } @@ -367,7 +368,8 @@ * @param alias for the entity in the query * @return the TopiaQuery */ - public TopiaQuery setFrom(Class<? extends TopiaEntity> mainEntityClass, String alias) { + public TopiaQuery setFrom(Class<? extends TopiaEntity> mainEntityClass, + String alias) { setFrom(mainEntityClass); mainAlias = alias; from.append(' ').append(alias); @@ -403,85 +405,12 @@ * @param alias of the entity in the query * @return the TopiaQuery */ - public TopiaQuery addFrom(Class<? extends TopiaEntity> entityClass, String alias) { + public TopiaQuery addFrom(Class<? extends TopiaEntity> entityClass, + String alias) { return addFrom(entityClass.getName() + " " + alias); } /** - * Create a TopiaQuery with entityClass initialization. - * - * @param <T> entity type extends TopiaEntity - * @param entityClass Class for an entity Query - * @return the new TopiaQuery - * @deprecated use constructor instead : - * {@link #TopiaQuery(TopiaDAO) } - */ - @Deprecated - public static <T extends TopiaEntity> TopiaQuery createQuery(Class<T> entityClass) { - return new TopiaQuery(entityClass); - } - - /** - * Create a TopiaQuery from a DAO. - * - * @param <T> entity type in the dao extends TopiaEntity - * @param dao DAO linked to the entity to threat - * @return the new TopiaQuery - * @deprecated use constructor instead : - * {@link #TopiaQuery(TopiaDAO) } - */ - @Deprecated - public static <T extends TopiaEntity> TopiaQuery createQuery(TopiaDAO<T> dao) { - return new TopiaQuery(dao); - } - - /** - * Create a TopiaQuery with entityClass initialization and its Alias. The main entity will be automatically added to the select part of - * the query if it is needed. - * - * @param <T> entity type in the dao extends TopiaEntity - * @param entityClass Class for an entity Query - * @param alias of the main entity in the query - * @return the new TopiaQuery - * @deprecated use constructor instead : - * {@link #TopiaQuery(Class, String) } - */ - @Deprecated - public static <T extends TopiaEntity> TopiaQuery createQuery(Class<T> entityClass, String alias) { - return new TopiaQuery(entityClass, alias); - } - - /** - * Create a TopiaQuery from a DAO with an Alias. The main entity will be automatically added to the select part of - * the query if it is needed. - * - * @param <T> entity type in the dao extends TopiaEntity - * @param dao DAO linked to the entity to threat - * @param alias of the main entity in the query - * @return the new TopiaQuery - * @deprecated use constructor instead : - * {@link #TopiaQuery(TopiaDAO, String) java.lang.Class) } - */ - @Deprecated - public static <T extends TopiaEntity> TopiaQuery createQuery(TopiaDAO<T> dao, String alias) { - return new TopiaQuery(dao, alias); - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(fullQuery()). - append("; (PARAMS : "). - append(getParams()). - append("); (LIMIT : "). - append(startIndex). - append(", "). - append(endIndex). - append(')'); - return result.toString(); -// return fullQuery() + "; (PARAMS : " + getParams() + "); (LIMIT : " + startIndex + ", " + endIndex + ")"; - } - - /** * Get the full query. * * @return a String corresponding to the full query. @@ -659,7 +588,8 @@ * ...) * @return the TopiaQuery */ - public TopiaQuery addNullOr(String paramName, Op constraint, Object paramValue) { + public TopiaQuery addNullOr(String paramName, Op constraint, + Object paramValue) { String valueName = getValueName(paramName); StringBuilder result = new StringBuilder(paramName).append(' ').append(Op.NULL). @@ -758,30 +688,6 @@ } /** - * Add an element to the query with a list of different values. The IN key - * word will be used to set the different values. An other constraint on - * nullity can be set with isNull argument. - * The element can have one of the value from the collection or can be null - * if the isNull argument is true. - * - * @param paramName name of the parameter in the query - * @param values different values for this parameter - * @param isNull use it to test the nullity of parameter - * @return the TopiaQuery - * @see #add(String) - * @deprecated use {@link #add(String, Object...) } - * with a null or not - */ - @Deprecated - public TopiaQuery add(String paramName, Collection<Object> values, - boolean isNull) { - if (isNull) { - values.add(null); - } - return add(paramName, values.toArray()); - } - - /** * Add a map of properties to the where clause of the query. Each property * will be added to the query with Op.EQ operation, the key in the map is * the property name, and the value is the value of the parameter in the @@ -805,6 +711,7 @@ * @param propertyA contains in propertyB collection * @param propertyB collection which contains propertyA * @return the TopiaQuery + * @since 2.4 */ public TopiaQuery addInElements(String propertyA, String propertyB) { StringBuilder builder = new StringBuilder(propertyA). @@ -970,13 +877,11 @@ public List execute(TopiaContext transaction) throws TopiaException { String query = fullQuery(); if (log.isDebugEnabled()) { - log.debug("# QUERY : " + query); - if (params != null) { - log.debug("# PARAMS : " + Arrays.toString(params.toArray())); - } + log.debug(this); } if (startIndex != null && endIndex != null) { - return transaction.find(query, startIndex, endIndex, getParams().toArray()); + return transaction.find(query, startIndex, endIndex, + getParams().toArray()); } return transaction.find(query, getParams().toArray()); } @@ -995,8 +900,7 @@ /** * Execute the query and get a List of entity. Some properties will be - * loaded if they are - * prealably set using ${@link #addLoad(String...) }. + * loaded if they are prealably set using ${@link #addLoad(String...) }. * * @param <E> * @param transaction the TopiaContext to use for execution @@ -1005,7 +909,8 @@ * @throws TopiaException * @throws ClassCastException */ - public <E extends TopiaEntity> List<E> executeToEntityList(TopiaContext transaction, Class<E> entityClass) + public <E extends TopiaEntity> List<E> executeToEntityList( + TopiaContext transaction, Class<E> entityClass) throws TopiaException, ClassCastException { List res = execute(transaction); if (log.isTraceEnabled()) { @@ -1023,7 +928,9 @@ o = ((Object[])o)[0]; } if (!entityClass.isAssignableFrom(o.getClass())) { - throw new ClassCastException(o.getClass().getName() + " can't be cast to " + entityClass.getName() + " o : " + o); + throw new ClassCastException(o.getClass().getName() + + " can't be cast to " + entityClass.getName() + + " o : " + o); } E entity = (E)o; // Check distinct constraint for complex query where o is firstly an @@ -1039,24 +946,6 @@ } /** - * DAO must be defined to use this method. - * - * @param <E> - * @return a List of TopiaEntity corresponding to the entityClass in argument - * @throws TopiaException - * @throws ClassCastException - * @see #executeToEntityList(TopiaContext,Class) - * @deprecated use dao method instead : - * {@link TopiaDAO#findAllByQuery(TopiaQuery) } - */ - @Deprecated - public <E extends TopiaEntity> List<E> executeToEntityList() - throws TopiaException, ClassCastException { - validateDAO(); - return (List<E>)dao.findAllByQuery(this); - } - - /** * Execute the query and get a Map of entity with key type in argument. Some * properties will be loaded if they are * prealably set using ${@link #addLoad(String...) }. @@ -1071,16 +960,20 @@ * @throws TopiaException * @throws ClassCastException */ - public <E extends TopiaEntity, K> Map<K, E> executeToEntityMap(TopiaContext transaction, Class<E> entityClass, String keyName, Class<K> keyClass) + public <E extends TopiaEntity, K> Map<K, E> executeToEntityMap( + TopiaContext transaction, Class<E> entityClass, + String keyName, Class<K> keyClass) throws TopiaException, ClassCastException { - // Use LinkedHashMap to keep insert order from list results which can be ordered + // Use LinkedHashMap to keep insert order from list results which + // can be ordered Map<K, E> results = new LinkedHashMap<K, E>(); List<E> list = executeToEntityList(transaction, entityClass); for (E elmt : list) { Object value = loadProperty(elmt, keyName); if (value != null && !keyClass.isAssignableFrom(value.getClass())) { - throw new ClassCastException(value.getClass().getName() + " can't be cast to " + keyClass.getName()); + throw new ClassCastException(value.getClass().getName() + + " can't be cast to " + keyClass.getName()); } results.put((K)value, elmt); } @@ -1088,27 +981,6 @@ } /** - * DAO must be defined to use this method. - * - * @param <E> - * @param <K> - * @param keyName - * @param keyClass - * @return a Map with the key type defined and the entity in value - * @throws TopiaException - * @throws ClassCastException - * @see #executeToEntityMap(TopiaContext, Class) - * @deprecated use dao method instead : - * {@link TopiaDAO#findAllMappedByQuery(TopiaQuery, String, Class) } - */ - @Deprecated - public <E extends TopiaEntity, K> Map<K, E> executeToEntityMap(String keyName, Class<K> keyClass) - throws TopiaException, ClassCastException { - validateDAO(); - return (Map<K, E>)dao.findAllMappedByQuery(this, keyName, keyClass); - } - - /** * Execute the query and get a Map of entity with topiaId in key. Some * properties will be loaded if they are * prealably set using ${@link #addLoad(String...) }. @@ -1120,30 +992,14 @@ * @throws TopiaException * @throws ClassCastException */ - public <E extends TopiaEntity> Map<String, E> executeToEntityMap(TopiaContext transaction, Class<E> entityClass) + public <E extends TopiaEntity> Map<String, E> executeToEntityMap( + TopiaContext transaction, Class<E> entityClass) throws TopiaException, ClassCastException { - return executeToEntityMap(transaction, entityClass, TopiaEntity.TOPIA_ID, String.class); + return executeToEntityMap(transaction, entityClass, + TopiaEntity.TOPIA_ID, String.class); } /** - * DAO must be defined to use this method. - * - * @param <E> - * @return a Map with the key type defined and the entity in value - * @throws TopiaException - * @throws ClassCastException - * @see #executeToEntityMap(TopiaContext,Class) - * @deprecated use dao method instead : - * {@link TopiaDAO#findAllMappedByQuery(TopiaQuery) } - */ - @Deprecated - public <E extends TopiaEntity> Map<String, E> executeToEntityMap() - throws TopiaException, ClassCastException { - validateDAO(); - return (Map<String, E>)dao.findAllMappedByQuery(this); - } - - /** * Execute the query and get the first result entity. Some properties will * be loaded if they are * prealably set using ${@link #addLoad(String...) }. @@ -1155,7 +1011,8 @@ * @throws TopiaException * @throws ClassCastException */ - public <E extends TopiaEntity> E executeToEntity(TopiaContext transaction, Class<E> entityClass) + public <E extends TopiaEntity> E executeToEntity(TopiaContext transaction, + Class<E> entityClass) throws TopiaException, ClassCastException { setMaxResults(1); List<E> results = executeToEntityList(transaction, entityClass); @@ -1164,25 +1021,6 @@ } /** - * DAO must be defined to use this method. - * - * @param <E> - * @return a TopiaEntity corresponding to the entityClass in argument - * @throws TopiaException - * @throws ClassCastException - * @see #executeToEntity(TopiaContext,Class) - * @deprecated use dao method instead : - * {@link TopiaDAO#findByQuery(TopiaQuery) } - */ - @Deprecated - public <E extends TopiaEntity> E executeToEntity() - throws TopiaException, ClassCastException { - validateDAO(); - //return executeToEntity(dao.getContext()); - return (E)dao.findByQuery(this); - } - - /** * Execute the query and get an Object for result. * The select is overriden to get only the right value for return. * @@ -1191,7 +1029,8 @@ * @return an Object * @throws TopiaException */ - public Object executeToObject(TopiaContext transaction, String select) throws TopiaException { + public Object executeToObject(TopiaContext transaction, String select) + throws TopiaException { StringBuilder oldValue = this.select; if (!StringUtils.isEmpty(select)) { setSelect(select); @@ -1217,7 +1056,8 @@ * @return an Integer * @throws TopiaException */ - public int executeToInteger(TopiaContext transaction, String select) throws TopiaException { + public int executeToInteger(TopiaContext transaction, String select) + throws TopiaException { Long res = (Long)executeToObject(transaction, select); return res != null ? res.intValue() : 0; } @@ -1244,7 +1084,8 @@ * @return a String * @throws TopiaException */ - public String executeToString(TopiaContext transaction, String select) throws TopiaException { + public String executeToString(TopiaContext transaction, String select) + throws TopiaException { Object res = executeToObject(transaction, select); return res != null ? (String)res : ""; } @@ -1277,7 +1118,12 @@ /** * Execute a simple count on the query, i.e. the number of results get from - * the query. The order is not considered to count the elements. + * the query. The order is not considered to count the elements and will + * be temporarly disabled. The distinct constraint will be manage if + * necessary : + * <pre> + * COUNT(DISTINCT mainAlias) + * </pre> * * @param transaction the TopiaContext to use for execution * @return an int corresponding to the number of result in the query @@ -1286,7 +1132,18 @@ public int executeCount(TopiaContext transaction) throws TopiaException { StringBuilder oldOrder = orderBy; orderBy = null; - int result = executeToInteger(transaction, "COUNT(*)"); + StringBuilder count = new StringBuilder("COUNT("); + // Ano #560 : manage distinct case when the alias is set (otherwise + // no need the distinct keyword because the entity type in query is + // unique) + if (distinct && StringUtils.isNotEmpty(mainAlias)) { + count.append("DISTINCT ").append(mainAlias); + // When distinct is not set, use * + } else { + count.append('*'); + } + count.append(')'); + int result = executeToInteger(transaction, count.toString()); orderBy = oldOrder; return result; } @@ -1307,7 +1164,7 @@ if (dao == null) { throw new TopiaException("DAO not defined in TopiaQuery, " + "can't execute it without TopiaContext"); - } + } return true; } @@ -1318,7 +1175,8 @@ * @param entity used to load properties * @throws TopiaException */ - protected <T extends TopiaEntity> void loadProperties(T entity) throws TopiaException { + protected <T extends TopiaEntity> void loadProperties(T entity) + throws TopiaException { for (String prop : getPropertiesToLoad()) { if (log.isTraceEnabled()) { log.trace("load property " + prop + " ..."); @@ -1329,7 +1187,8 @@ while (it.hasNext()) { String s = it.next(); if (log.isTraceEnabled()) { - log.trace("Current entity : " + currEntity.getClass().getSimpleName()); + log.trace("Current entity : " + + currEntity.getClass().getSimpleName()); log.trace("Current loading : " + s); } if (it.hasNext()) { @@ -1350,7 +1209,8 @@ * @return a TopiaEntity corresponding to the property loaded * @throws TopiaException */ - protected <T extends TopiaEntity> TopiaEntity loadEntityProperty(T entity, String property) throws TopiaException { + protected <T extends TopiaEntity> TopiaEntity loadEntityProperty(T entity, + String property) throws TopiaException { return (TopiaEntity)loadProperty(entity, property); } @@ -1363,11 +1223,13 @@ * @return an Object corresponding to the property loaded * @throws TopiaException */ - protected <T extends TopiaEntity> Object loadProperty(T entity, String property) throws TopiaException { + protected <T extends TopiaEntity> Object loadProperty(T entity, + String property) throws TopiaException { try { Object res = PropertyUtils.getProperty(entity, property); if (log.isTraceEnabled()) { - log.trace("load property '" + property + "' for '" + entity.getClass().getSimpleName() + "'"); + log.trace("load property '" + property + "' for '" + + entity.getClass().getSimpleName() + "'"); } if (res != null && Collection.class.isAssignableFrom(res.getClass())) { Collection<?> list = (Collection<?>) res; @@ -1375,35 +1237,35 @@ } return res; } catch (IllegalAccessException eee) { - throw new TopiaException("Illegal access on property " + property + " from entity " + entity.getClass().getName(), eee); + throw new TopiaException("Illegal access on property " + + property + " from entity " + + entity.getClass().getName(), eee); } catch (InvocationTargetException eee) { - throw new TopiaException("Invocation error on entity " + entity.getClass().getName() + " for property " + property, eee); + throw new TopiaException("Invocation error on entity " + + entity.getClass().getName() + " for property " + + property, eee); } catch (NoSuchMethodException eee) { - throw new TopiaException("Getter method does not exist for property " + property + " from entity " + entity.getClass().getName(), eee); + throw new TopiaException("Getter method does not exist for" + + " property " + property + " from entity " + + entity.getClass().getName(), eee); } } - @Override - protected void finalize() { - // Clean StringBuilder statements - select = null; - from = null; - where = null; - orderBy = null; - groupBy = null; - } - /** * This method is used to concat properties from entities. Ex in HQL you * can have boat.shipOwner.name, these properties are defined as constants * in each entity associated (SHIP_OWNER in Boat entity, NAME in ShipOwner * entity) so you just have to call this method as : - * getProperty("boat", Boat.SHIP_OWNER, ShipOwner.NAME); to have the - * correct property to use : boat.shipOwner.name. It's better to use - * constants instead of directly the string chain to avoid problems on - * changing property name in model. Furthermore it's better to use this - * method instead of doing : + * <pre> + * getProperty("boat", Boat.SHIP_OWNER, ShipOwner.NAME); + * // will return boat.shipOwner.name + * </pre><br \> + * It's better to use constants instead of directly the string chain to + * avoid problems on changing property name in model. Furthermore it's + * better to use this method instead of doing : + * <pre> * "boat." + Boat.SHIP_OWNER + "." + ShipOwner.NAME + * </pre> * * @param entityProperty to concat * @return the string chain with properties separated with a dot @@ -1414,4 +1276,27 @@ return result; } + @Override + protected void finalize() { + // Clean StringBuilder statements + select = null; + from = null; + where = null; + orderBy = null; + groupBy = null; + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(fullQuery()). + append("; (PARAMS : "). + append(getParams()). + append("); (LIMIT : "). + append(startIndex). + append(", "). + append(endIndex). + append(')'); + return result.toString(); + } + }
participants (1)
-
fdesbois@users.nuiton.org