2010-12-28 9 views
7

Uso un ContentProvider para hablar con la base de datos de mi aplicación y me encuentro con un pequeño problema.Manera elegante de hacer consultas crudas complejas usando un ContentProvider

Tengo una consulta que es un poco complicada. Se ve algo como esto:

String sql = 
    "select " + 
    " tblHistory._id _id, " + 
    " tblHistory.item item, " + 
    " tblHistory.updated_on updated_on, " + 
    " (select _id from tblList " + 
     "where tblList.item = tblHistory.item) list_id, " + 
    " 1 priority, " + 
    "from " + 
    " tblHistory " + 
    "where " + 
    " tblHistory.status <> 'STATE_DELETING' and " + selection + " " + 
    "union " + 
    "select " + 
    " tblSearch._id _id, " + 
    " tblSearch.item item, " + 
    " -1 updated_on, " + 
    " (select _id from tblList " + 
     "where tblList.item = tblSearch.product_name) list_id, " + 
    " 2 priority, " + 
    "from " + 
    " tblSearch " + 
    "where " + 
    " not exists (select * from tblHistory " + 
     "where tblHistory.item = tblSearch.product_name) " + 
    "order by " + 
    " priority, _id asc"; 

    c = mDb.rawQuery(sql, null); 

selección es:

String where = "tblHistory.user_id=" 
       + Integer.toString(intUserId) 
       + " and tblHistory.item like '%" 
       + strSearch + "%'"; 

Mi problema es mis sub-consultas. Tengo una restricción que necesito agregar, pero no hay una buena manera de llevar esa restricción al camino del método. Necesito usar el user_id correcto en las sub-consultas.

En este punto, creo que tengo 2 opciones:

1) analizar fuera de la user_id parcial de caracteres de la selección.

2) Use selectionArgs como un truco para pasar "user_id = " + Integer.toString(intUserId) al método.

¿Alguna otra idea?

Debo señalar que aunque preferiría no hacer nada hack-ish, he hecho que mi ContentProvider sea privada, ya que está destinada a ser utilizada solo por mi aplicación; entonces si tengo que hacerlo, puedo.

+1

Hágase un favor y el uso ' "" + intUserId' en lugar de' Integer.toString (intUserId) '. : p –

+0

Vea http://stackoverflow.com/a/6548733/633187. ¿Responde esto a tu pregunta? – jcwenger

+1

Andrew, para expandir el comentario de Alex (esto es un poco fuera de tema y no aborda su problema real): La forma más eficiente de convertir ints a cadenas en Java es usando Integer.toString, pero si va a Concatenar el resultado con una Cadena, puede escribir: Cadena donde = "tblHistory.user_id =" + intUserId + "y tblHistory.item como '%' + strSearch +"% '"; –

Respuesta

2

cuando se trata de consultas complejas como esta, una clase de generador puede ser útil. Te evita tener que convertirlos a String, espero que esto te ayude.

public class SqlQueryBuilder { 

private static final String SELECT = "SELECT"; 

private static final String COMA = " , "; 

private static final String WHERE = " where "; 

private static final String EQUALS = " = "; 

private static final String NOT_EQUALS = " != "; 

private static final String FROM = " FROM "; 

private final StringBuilder mStrBuilder = new StringBuilder(); 

public void init() { 
    mStrBuilder.setLength(0); 
} 

public SqlQueryBuilder select(Object ...columns) { 
    mStrBuilder.append(SELECT); 
    for(Object column:columns) { 
     mStrBuilder.append(column); 
     mStrBuilder.append(COMA); 
    } 
    return this; 
} 

public SqlQueryBuilder where(Object conditionVar) { 
    mStrBuilder.append(WHERE); 
    mStrBuilder.append(conditionVar); 
    return this; 
} 


public SqlQueryBuilder equalsVal(Object equalsVal) { 
    mStrBuilder.append(EQUALS); 
    mStrBuilder.append(equalsVal); 
    return this; 
} 

public SqlQueryBuilder notEqualsVal(Object notEqualsVal) { 
    mStrBuilder.append(NOT_EQUALS); 
    mStrBuilder.append(notEqualsVal); 
    return this; 
} 

public SqlQueryBuilder from(Object from) { 
    mStrBuilder.append(FROM); 
    mStrBuilder.append(from); 
    return this; 
} 

public String build() { 
    final String sqlQuery = mStrBuilder.toString(); 
    init(); 
    return sqlQuery; 
} 

}

El uso es como a continuación

{ 

    SqlQueryBuilder sqlQueryBuilder = new SqlQueryBuilder(); 

    String innerQuery = sqlQueryBuilder.select("_id").from("tblList") 
      .where("tblList.item").equalsVal("tblHistory.item").build(); 

    String query = sqlQueryBuilder.select("tblHistory._id _id", 
      "tblHistory.item", "tblHistory.updated_on updated_on", 
      innerQuery + " list_id", "1 priority").build(); 

} 
Cuestiones relacionadas