/* * Copyright 2004-2011 H2 Group. * Copyright 2011 James Moger. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.iciql; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * A class that implements this interface can be used as a database table. * <p> * You may implement the Table interface on your model object and optionally use * IQColumn annotations (which imposes a compile-time and runtime-dependency on * iciql), or may choose to use the IQTable and IQColumn annotations only (which * imposes a compile-time and runtime-dependency on this file only). * <p> * If a class is annotated with IQTable and at the same time implements Table, * the define() method is not called. * <p> * Fully Supported Data Types: * <table> * <tr> * <th colspan="2">All Databases</th> * </tr> * <tr> * <td>java.lang.String</td> * <td>VARCHAR (length > 0) or TEXT (length == 0)</td> * </tr> * <tr> * <td>java.lang.Boolean</td> * <td>BIT</td> * </tr> * <tr> * <td>java.lang.Byte</td> * <td>TINYINT</td> * </tr> * <tr> * <td>java.lang.Short</td> * <td>SMALLINT</td> * </tr> * <tr> * <td>java.lang.Integer</td> * <td>INT</td> * </tr> * <tr> * <td>java.lang.Long</td> * <td>BIGINT</td> * </tr> * <tr> * <td>java.lang.Float</td> * <td>REAL</td> * </tr> * <tr> * <td>java.lang.Double</td> * <td>DOUBLE</td> * </tr> * <tr> * <td>java.math.BigDecimal</td> * <td>DECIMAL</td> * </tr> * <tr> * <td>java.sql.Date</td> * <td>DATE</td> * </tr> * <tr> * <td>java.sql.Time</td> * <td>TIME</td> * </tr> * <tr> * <td>java.sql.Timestamp</td> * <td>TIMESTAMP</td> * </tr> * <tr> * <td>java.util.Date</td> * <td>TIMESTAMP</td> * </tr> * <tr> * <td>java.lang.Enum.name()</td> * <td>VARCHAR (length > 0) or TEXT (length == 0)<br/> * EnumType.NAME</td> * </tr> * <tr> * <td>java.lang.Enum.ordinal()</td> * <td>INT<br/> * EnumType.ORDINAL</td> * </tr> * <tr> * <td>java.lang.Enum implements<br/> * com.iciql.Iciql.EnumID.enumId()</td> * <td>INT<br/> * EnumType.ENUMID</td> * </tr> * <tr> * <th colspan="2">H2 Databases</th> * </tr> * <tr> * <td>java.util.UUID</td> * <td>UUID</td> * </tr> * </table> * <p> * Partially Supported Data Types: * <p> * The following data types can be mapped to columns for all general statements * BUT these field types may not be used to specify compile-time clauses or * constraints. * <table> * <tr> * <td>byte []</td> * <td>BLOB</td> * </tr> * <tr> * <td>boolean</td> * <td>BIT</td> * </tr> * <tr> * <td>byte</td> * <td>TINYINT</td> * </tr> * <tr> * <td>short</td> * <td>SMALLINT</td> * </tr> * <tr> * <td>int</td> * <td>INT</td> * </tr> * <tr> * <td>long</td> * <td>BIGINT</td> * </tr> * <tr> * <td>float</td> * <td>REAL</td> * </tr> * <tr> * <td>double</td> * <td>DOUBLE</td> * </tr> * </table> * <p> * Table and field mapping: by default, the mapped table name is the class name * and the public fields are reflectively mapped, by their name, to columns. As * an alternative, you may specify both the table and column definition by * annotations. * <p> * Table Interface: you may set additional parameters such as table name, * primary key, and indexes in the define() method. * <p> * Annotations: you may use the annotations with or without implementing the * Table interface. The annotations allow you to decouple your model completely * from iciql other than this file. * <p> * Automatic model generation: you may automatically generate model classes as * strings with the Db and DbInspector objects: * * <pre> * Db db = Db.open("jdbc:h2:mem:", "sa", "sa"); * DbInspector inspector = new DbInspector(db); * List<String> models = * inspector.generateModel(schema, table, packageName, * annotateSchema, trimStrings) * </pre> * * Or you may use the GenerateModels tool to generate and save your classes to * the file system: * * <pre> * java -jar iciql.jar * -url "jdbc:h2:mem:" * -user sa -password sa -schema schemaName -table tableName * -package packageName -folder destination * -annotateSchema false -trimStrings true * </pre> * * Model validation: you may validate your model class with DbInspector object. * The DbInspector will report errors, warnings, and suggestions: * * <pre> * Db db = Db.open("jdbc:h2:mem:", "sa", "sa"); * DbInspector inspector = new DbInspector(db); * List<Validation> remarks = inspector.validateModel(new MyModel(), throwOnError); * for (Validation remark : remarks) { * System.out.println(remark); * } * </pre> */ public interface Iciql { /** * An annotation for an iciql version. * <p> * * @IQVersion(1) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface IQVersion { /** * If set to a non-zero value, iciql maintains a "_iq_versions" table * within your database. The version number is used to call to a * registered DbUpgrader implementation to perform relevant ALTER * statements. Default: 0. You must specify a DbUpgrader on your Db * object to use this parameter. */ int value() default 0; } /** * An annotation for a schema. * <p> * * @IQSchema("PUBLIC") */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface IQSchema { /** * The schema may be optionally specified. Default: unspecified. */ String value() default ""; } /** * Enumeration defining the four index types. */ public static enum IndexType { STANDARD, UNIQUE, HASH, UNIQUE_HASH; } /** * An index annotation. * <p> * <ul> * <li>@IQIndex("name") * <li>@IQIndex({"street", "city"}) * <li>@IQIndex(name="streetidx", value={"street", "city"}) * <li>@IQIndex(name="addressidx", type=IndexType.UNIQUE, * value={"house_number", "street", "city"}) * </ul> */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface IQIndex { /** * Index name. If null or empty, iciql will generate one. */ String name() default ""; /** * Type of the index. * <ul> * <li>com.iciql.iciql.IndexType.STANDARD * <li>com.iciql.iciql.IndexType.UNIQUE * <li>com.iciql.iciql.IndexType.HASH * <li>com.iciql.iciql.IndexType.UNIQUE_HASH * </ul> * * HASH indexes may only be valid for single column indexes. * */ IndexType type() default IndexType.STANDARD; /** * Columns to include in index. * <ul> * <li>single column index: value = "id" * <li>multiple column index: value = { "id", "name", "date" } * </ul> */ String[] value() default {}; } /** * Annotation to specify multiple indexes. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface IQIndexes { IQIndex[] value() default {}; } /** * Annotation to define a table. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface IQTable { /** * The table name. If not specified the class name is used as the table * name. * <p> * The table name may still be overridden in the define() method if the * model class is not annotated with IQTable. Default: unspecified. */ String name() default ""; /** * The primary key may be optionally specified. If it is not specified, * then no primary key is set by the IQTable annotation. You may specify * a composite primary key. * <ul> * <li>single column primaryKey: value = "id" * <li>compound primary key: value = { "id", "name" } * </ul> * The primary key may still be overridden in the define() method if the * model class is not annotated with IQTable. Default: unspecified. */ String[] primaryKey() default {}; /** * The inherit columns allows this model class to inherit columns from * its super class. Any IQTable annotation present on the super class is * ignored. Default: false. */ boolean inheritColumns() default false; /** * Whether or not iciql tries to create the table and indexes. Default: * true. */ boolean createIfRequired() default true; /** * Whether only supported types are mapped. If true, unsupported mapped * types will throw an IciqlException. If false, unsupported mapped * types will default to VARCHAR. Default: true. */ boolean strictTypeMapping() default true; /** * If true, only fields that are explicitly annotated as IQColumn are * mapped. Default: true. */ boolean annotationsOnly() default true; /** * If true, this table is created as a memory table where data is * persistent, but index data is kept in main memory. Valid only for H2 * databases. Default: false. */ boolean memoryTable() default false; } /** * Annotation to define a column. Annotated fields may have any scope * (however, the JVM may raise a SecurityException if the SecurityManager * doesn't allow iciql to access the field.) */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface IQColumn { /** * If not specified, the field name is used as the column name. Default: * the field name. */ String name() default ""; /** * This column is the primary key. Default: false. */ boolean primaryKey() default false; /** * The column is created with a sequence as the default value. Default: * false. */ boolean autoIncrement() default false; /** * If larger than zero, it is used during the CREATE TABLE phase. It may * also be used to prevent database exceptions on INSERT and UPDATE * statements (see trim). * <p> * Any length set in define() may override this annotation setting if * the model class is not annotated with IQTable. Default: 0. */ int length() default 0; /** * If true, iciql will automatically trim the string if it exceeds * length (value.substring(0, length)). Default: false. */ boolean trim() default false; /** * If false, iciql will set the column NOT NULL during the CREATE TABLE * phase. Default: false. */ boolean allowNull() default false; /** * The default value assigned to the column during the CREATE TABLE * phase. This field could contain a literal single-quoted value, or a * function call. Empty strings are considered NULL. Examples: * <ul> * <li>defaultValue="" (null) * <li>defaultValue="CURRENT_TIMESTAMP" * <li>defaultValue="''" (empty string) * <li>defaultValue="'0'" * <li>defaultValue="'1970-01-01 00:00:01'" * </ul> * if the default value is specified, and auto increment is disabled, * and primary key is disabled, then this value is included in the * "DEFAULT ..." phrase of a column during the CREATE TABLE process. * <p> * Alternatively, you may specify a default object value on the field * and this will be converted to a properly formatted DEFAULT expression * during the CREATE TABLE process. * <p> * Default: unspecified (null). */ String defaultValue() default ""; } /** * Interface for using the EnumType.ENUMID enumeration mapping strategy. * <p> * Enumerations wishing to use EnumType.ENUMID must implement this * interface. */ public interface EnumId { int enumId(); } /** * Enumeration representing how to map a java.lang.Enum to a column. * <p> * <ul> * <li>NAME - name() : string * <li>ORDINAL - ordinal() : int * <li>ENUMID - enumId() : int * </ul> * * @see com.iciql.Iciql.EnumId interface */ public enum EnumType { NAME, ORDINAL, ENUMID; public static final EnumType DEFAULT_TYPE = NAME; } /** * Annotation to define how a java.lang.Enum is mapped to a column. * <p> * This annotation can be used on: * <ul> * <li>a field instance of an enumeration type * <li>on the enumeration class declaration * </ul> * If you choose to annotate the class declaration, that will be the default * mapping strategy for all @IQColumn instances of the enum. This can still * be overridden for an individual field by specifying the IQEnum * annotation. * <p> * The default mapping is by NAME. * * <pre> * IQEnum(EnumType.NAME) * </pre> * * A string mapping will generate either a VARCHAR, if IQColumn.length > 0 * or a TEXT column if IQColumn.length == 0 * */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.TYPE }) public @interface IQEnum { EnumType value() default EnumType.NAME; } /** * This method is called to let the table define the primary key, indexes, * and the table name. */ @Deprecated void defineIQ(); }