1 /**
2  * HibernateD - Object-Relation Mapping for D programming language, with interface similar to Hibernate. 
3  * 
4  * Hibernate documentation can be found here:
5  * $(LINK http://hibernate.org/docs)$(BR)
6  * 
7  * Source file hibernated/annotations.d.
8  *
9  * This module contains declarations of HibernateD Annotations - User Defined Attribues used to markup D classes and their properties for ORM.
10  * 
11  * Copyright: Copyright 2013
12  * License:   $(LINK www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
13  * Author:   Vadim Lopatin
14  */
15 module hibernated.annotations;
16 
17 
18 
19 /**
20  * @Transient - mark class or field as transient, to not generate HibernateD persistence metadata for it.
21  * Use this annotation in cases when field you won't persist will be considered as persistent otherwise.
22  */
23 struct Transient {
24     immutable bool dummy;
25 }
26 
27 
28 /** 
29  * Class level annotations.
30  * 
31  * HibernateD maps values of some class to DB table. This class is referred as Entity.
32  * 
33  * Entity contains one or more properties - which are usually mapped to DB table columns.
34  */
35 
36 /**
37  * Mark class with this annotation if you want to make it persistable.
38  * @Entity or @Entity() - marks class as entity, using class name as entity name.
39  */
40 struct Entity {
41 	//immutable string name;
42     immutable bool dummy;
43     //	this(string name) { this.name = name; }
44 }
45 
46 /**
47  * @Embeddable or @Embeddable() - mark class as entity which can only be embedded into other entities, and doesn't have separate columns.
48  * Columns for each of Embeddable entity properties will be placed into parent entity's table, where this embeddable entity is embedded
49  */
50 struct Embeddable {
51 	immutable bool dummy;
52 //	this(bool enabled) {}
53 }
54 
55 /**
56  * While the `@Embeddable` annotation is applied to a type which can be included in a class in order
57  * to add its properties as its own, the `@Embedded` annotation is used for the field itself.
58  *
59  * If there is only one `@Embeddable` member in a class, then this annotation is implied and
60  * optional. However, `@Embedded` can include a prefix, which is needed to distinguish multiple
61  * embedded properties that have the same type.
62  *
63  * Example:
64  * ```
65  * @Embeddable
66  * class Address {
67  *   string zip;
68  *   string city;
69  *   string streetAddress;
70  * }
71  *
72  * @Table("customers")
73  * class Customer {
74  *   @Id @Generated
75  *   long id;
76  *
77  *   @Embedded("shipping")
78  *   Address shipping;  // Adds columns like: shipping_zip, shipping_city
79  *
80  *   @Embedded("billing")
81  *   Address billing;  // Adds columns like: billing_zip, billing_city
82  * }
83  * ```
84  */
85 struct Embedded {
86   string columnPrefix;
87 }
88 
89 /**
90  * Use to specify table name for entity.
91  * @Table("table_name") - specifies table name to store entity in, different from default generated.
92  * If this annotation not present, table name will be autogenerated as lowercase entity name with conversion of 
93  * CamelCaseEntityName to camel_case_entity_name.
94  */
95 struct Table {
96 	immutable string name;
97 //	this(string name) { this.name = name; }
98 }
99 
100 /** 
101  * Property level annotations.
102  * 
103  * Supported simple types for properties (may be stored in single DB table column):
104  *     byte, short, int, long, ubyte, ushort, uint, ulong, float, double, byte[], ubyte[], string, DateTime, Date, TimeOfDay
105  * 
106  * Other possible types of properties:
107  *     Embeddable entity class -- implementation in progress
108  *     Entity class Lazy!class -- ManyToOne or OneToOne relation
109  *     Entity class array or LazyCollection!class -- collection for OneToMany or ManyToMany
110  * 
111  * Supported kinds of property holders:
112  *     field -- just public field
113  *     @property -- D language read/write property
114  *     getField()/setField(x) method pair
115  * 
116  * Each entity property has a name. It's derived from field, @property or getter/setter name.
117  * For field and D @property - name of field of property is used as name of entity property, with first letter lowercased.
118  * For getters/setters, get/set/is prefix is removed from mothod name, and the rest with lowercased first letter is used as property name.
119  */
120 
121 /**
122  * Mark property as simple persistent property (must be of one of simple types).
123  * 
124  * @Column or @Column() - simple column, with name derived from field/property name.
125  * @Column("column_name") - simple column with specified name.
126  * @Column("column_name", field_length) - simple column with specified name and length (e.g. for varchar).
127  * @Column(field_length) - simple column with specified length; column name will be autogenerated
128  * 
129  * If column name is not specified, lowercased name of property with _ delimited camelCase words is used as column name.
130  * Field name camelCasePropertyName will be converted to camel_case_property_name column name.
131  */
132 struct Column {
133 	immutable string name;
134 	immutable int length;
135 //	this(string name) { this.name = name; }
136 //	this(string name, int length) { this.name = name; this.length = length; }
137 //	this(int length) { this.length = length; }
138 }
139 
140 /**
141  * @Id or @Id() - mark simple property as primary key of entity.
142  */
143 struct Id {
144 	immutable bool dummy;
145 }
146 
147 /**
148  * @Generated or @Generated() - mark simple property as column as server generated value (e.g. AUTO INCREMENT field)
149  */
150 struct Generated {
151 	immutable bool dummy;
152 }
153 
154 /**
155  * @Generator(code) - specify code to call for generation of simple property key value (will be inserted into definition Variant function(Connection conn, PropertyInfo prop) { return Variant($code); }
156  */
157 struct Generator {
158     string code;
159 }
160 
161 /// standard generator - generates random UUID - for use as @Generator() annotation parameter. Don't forget to import std.uuid
162 const string UUID_GENERATOR = "std.uuid.randomUUID().toString()";
163 
164 /**
165  * @NotNull or @NotNull() - mark entity property as not null (NULLs are not allowed in DB)
166  * If neither @NotNull nor @Null specified, nullability will be derived from field type (e.g. NotNull for int, long; Null for string, byte[], Nullable!int)
167  */
168 struct NotNull {
169 	immutable bool dummy;
170 }
171 
172 /**
173  * @Null or @Null() - mark entity property as nullable (NULLs are allowed in DB)
174  * If neither @NotNull nor @Null specified, nullability will be derived from field type (e.g. NotNull for int, long; Null for string, byte[], Nullable!int)
175  */
176 struct Null {
177 	immutable bool dummy;
178 }
179 
180 /**
181  * @UniqueKey or @UniqueKey() - mark entity property as unique (UNIQUE INDEX will be created for this column, with autogenerated index name)
182  * @UniqueKey(indexName) - mark entity property as unique (UNIQUE INDEX will be created for this column, with specified index name)
183  * For multiple column unique constraints, use Entity level annotations (TODO).
184  */
185 struct UniqueKey {
186     immutable string name;
187 }
188 
189 
190 /**
191  * @OneToOne(propertyName) - referenced object uses one-to-one relation, propertyName is referenced entity's property to join with current entity's primary key.
192  * @OneToOne or @OneToOne() - referenced object uses one-to-one relation, requires additional @JoinColumn annotation to specify foreign key column in current entity to join with current entity's primary key.
193  */
194 struct OneToOne {
195 	immutable string name;
196 //	this(string referencedPropertyName) { this.name = name; }
197 }
198 
199 /**
200  * @ManyToOne or @ManyToOne() - referenced object uses many-to-one relation, requires additional @JoinColumn annotation to specify foreign key column in current entity to join with current entity's primary key.
201  */
202 struct ManyToOne {
203     immutable bool dummy;
204 }
205 
206 /**
207  * @JoinColumn(columnName) - specify foreign key column name to join other entity's by its primary key - for @OneToOne relation.
208  * @JoinColumn or @JoinColumn() - foreign key column name will be autogenerated from referenced entity name, with _fk suffix.
209  * This annotation is mandatory if property has @OneToOne annotation w/o parameter or @ManyToOne annotation
210  */
211 struct JoinColumn {
212 	immutable string name;
213 //	this(string columnName) { this.name = name; }
214 }
215 
216 /**
217  * @OneToMany(referencedProperty) - referenced objects use one-to-many relation, requires additional property name in target entity which has specified foreign key column and ManyToOne to join with current entity's primary key.
218  */
219 struct OneToMany {
220     immutable string name;
221 }
222 
223 /**
224  * @ManyToMany(joinTableName, joinColumn1, joinColumn2) - referenced objects use many-to-many relation via additional join table, requires additional parameters to specify join table to implement relation, and fk columns to referene this and related entities.
225  * @ManyToMany or @ManyToMany() - referenced objects use many-to-many relation via additional join table, will autogenerate join table name to implement relation, and fk column names to referene this and related entities.
226  */
227 struct ManyToMany {
228     immutable string joinTableName;
229     immutable string joinColumn1;
230     immutable string joinColumn2;
231 }
232 
233 
234 unittest {
235 
236 	@Entity
237 	@Table("user")
238 	class User {
239 
240 		@Id @Generated
241 		@Column("id")
242 		int id;
243 
244 		@Column("name")
245 		string name;
246 	}
247 
248 }