001package com.avaje.ebean; 002 003import java.sql.ResultSet; 004 005import com.avaje.ebean.RawSql.ColumnMapping; 006import com.avaje.ebean.RawSql.Sql; 007 008/** 009 * Builds RawSql instances from a SQL string and column mappings. 010 * <p> 011 * Note that RawSql can also be defined in ebean-orm.xml files and be used as a 012 * named query. 013 * </p> 014 * 015 * @see RawSql 016 */ 017public class RawSqlBuilder { 018 019 /** 020 * Special property name assigned to a DB column that should be ignored. 021 */ 022 public static final String IGNORE_COLUMN = "$$_IGNORE_COLUMN_$$"; 023 024 private final ResultSet resultSet; 025 026 private final Sql sql; 027 028 private final ColumnMapping columnMapping; 029 030 /** 031 * Create and return a RawSql object based on the resultSet and list of properties the columns in 032 * the resultSet map to. 033 * <p> 034 * The properties listed in the propertyNames must be in the same order as the columns in the 035 * resultSet. 036 */ 037 public static RawSql resultSet(ResultSet resultSet, String... propertyNames) { 038 return new RawSql(resultSet, propertyNames); 039 } 040 041 /** 042 * Return an unparsed RawSqlBuilder. Unlike a parsed one this query can not be 043 * modified - so no additional WHERE or HAVING expressions can be added to 044 * this query. 045 */ 046 public static RawSqlBuilder unparsed(String sql) { 047 048 Sql s = new Sql(sql); 049 return new RawSqlBuilder(s, new ColumnMapping()); 050 } 051 052 /** 053 * Return a RawSqlBuilder parsing the sql. 054 * <p> 055 * The sql statement will be parsed so that Ebean can determine where it can 056 * insert additional WHERE or HAVING expressions. 057 * </p> 058 * <p> 059 * Additionally the selected columns are parsed to determine the column 060 * ordering. This also means additional checks can be made with the column 061 * mapping - specifically we can check that all columns are mapped and that 062 * correct column names are entered into the mapping. 063 * </p> 064 */ 065 public static RawSqlBuilder parse(String sql) { 066 067 Sql sql2 = DRawSqlParser.parse(sql); 068 String select = sql2.getPreFrom(); 069 070 ColumnMapping mapping = DRawSqlColumnsParser.parse(select); 071 return new RawSqlBuilder(sql2, mapping); 072 } 073 074 private RawSqlBuilder(Sql sql, ColumnMapping columnMapping) { 075 this.sql = sql; 076 this.columnMapping = columnMapping; 077 this.resultSet = null; 078 } 079 080 /** 081 * Set the mapping of a DB Column to a bean property. 082 * <p> 083 * For Unparsed SQL the columnMapping MUST be defined in the same order that 084 * the columns appear in the SQL statement. 085 * </p> 086 * 087 * @param dbColumn 088 * the DB column that we are mapping to a bean property 089 * @param propertyName 090 * the bean property that we are mapping the DB column to. 091 */ 092 public RawSqlBuilder columnMapping(String dbColumn, String propertyName) { 093 columnMapping.columnMapping(dbColumn, propertyName); 094 return this; 095 } 096 097 /** 098 * Ignore this DB column. It is not mapped to any bean property. 099 */ 100 public RawSqlBuilder columnMappingIgnore(String dbColumn) { 101 return columnMapping(dbColumn, IGNORE_COLUMN); 102 } 103 104 /** 105 * Modify any column mappings with the given table alias to have the path prefix. 106 * <p> 107 * For example modify all mappings with table alias "c" to have the path prefix "customer". 108 * </p> 109 * <p> 110 * For the "Root type" you don't need to specify a tableAliasMapping. 111 * </p> 112 */ 113 public RawSqlBuilder tableAliasMapping(String tableAlias, String path) { 114 columnMapping.tableAliasMapping(tableAlias, path); 115 return this; 116 } 117 118 /** 119 * Create the immutable RawSql object. Do this after all the column mapping 120 * has been defined. 121 */ 122 public RawSql create() { 123 return new RawSql(resultSet, sql, columnMapping.createImmutableCopy()); 124 } 125 126 /** 127 * Return the internal parsed Sql object (for testing). 128 */ 129 protected Sql getSql() { 130 return sql; 131 } 132 133 134 135}