April 04, 2013
On 2013-04-04 11:01, Jacob Carlborg wrote:

> Perhaps for primitive types you could have:
>
> class User
> {
>      Long id;
>      String name;
>      Int foo;
> }
>
> Note the capital letters.
>

Or:

Id id;

-- 
/Jacob Carlborg
April 04, 2013
On Wednesday, 3 April 2013 at 19:07:39 UTC, Vadim Lopatin wrote:
> I don't see what to simplify in markup like this:
> ...

You may implement approach similar to one used in vibe.d http.rest and http.form modules. Some specific examples are described by Jacob, but, in general, in results in 3 configuration stages:
0) No configuration at all, all data is inferred from variable names and types according to some sane convention.
1) Convention configuration - you chose one convention to use for aggregate type introspection at compile-time. Few different pre-defined conventions exist.
2) Fine configuration using UDAs.
April 04, 2013
On Thursday, 4 April 2013 at 09:01:16 UTC, Jacob Carlborg wrote:
> Is the attributes necessary at all? I would just go with:
>
> class User
> {
>     long id; // always assume auto increment, primary key, not null and so on
>     string name;
>     Customer customer; // infer @ManyToOne
>     @ManyToMany LazyCollection!Role roles; // I guess this cannot be inferred
>     LazyCollection!Foo foos; // infer @OneToMany
> }
>
> Perhaps for primitive types you could have:
>
> class User
> {
>     Long id;
>     String name;
>     Int foo;
> }
>
> Note the capital letters.

In Hibernate, there are two modes of automatic extraction of properties from clas: all fields or all getters/setters. Unless field or getter has no @Transient annotation, it's considered as property.
I can implement similar behavior.

If class doesn't have class level annotations, we can treat it as @Entity.
But in this case it's impossible to find entity classes in modules. Currently, HibernateD accept list of classes and/or modules, to extract metadata from.
If module is passed, how would we determine if some particular class in module is persistent or not? Either we have to import ALL classes of module as entities or only annotated.

Having default @ManyToOne for object field and @OneToMany for array of objects is a good idea.

It will be nice to define aliases like alias Nullable!long Long;

The question is how to determine what members of class to treat as properties?
Currently field, getter/setter pair, and @property supported. What should be rule to choose which of them import as fields?
Have a priority of @property access functions and getters/setters over usual fields? Ignore private and protected members?

BTW, having getField()/setField() looks like not a D way (@property should be used instead). Probably, I just can remove getters/setters support.
April 05, 2013
On Thursday, 4 April 2013 at 09:54:48 UTC, Dicebot wrote:
> On Wednesday, 3 April 2013 at 19:07:39 UTC, Vadim Lopatin wrote:
>> I don't see what to simplify in markup like this:
>> ...
>
> You may implement approach similar to one used in vibe.d http.rest and http.form modules. Some specific examples are described by Jacob, but, in general, in results in 3 configuration stages:
> 0) No configuration at all, all data is inferred from variable names and types according to some sane convention.
> 1) Convention configuration - you chose one convention to use for aggregate type introspection at compile-time. Few different pre-defined conventions exist.
> 2) Fine configuration using UDAs.


Implemented changes for better convention-over-configuration:
- If no annotations on class level, @Entity is assumed.
- No required annotation for simple properties. Nullability is deduced from data type
- @Embedded annotation is not needed anymore - it's deduced from field's class @Embeddable annotation
- If no key field annotations specified in class (@Id, @Generated, @Generator) - property named "id" (if any) is considered to be a @Generated primary key.
- For Object fields @ManyToOne is applied by default
- For Object[] or LazyCollection!Object @OneToMany is applied by default
- @OneToOne and @ManyToOne are required, since cannot be deduced

Following declarations are valid (comments describe ):

// @Entity assumed since no @Embeddable annotation
class User {
   long id;         // @Generated deduced from field name
   string name;     // deduced @NotNull
   Address address; // deduced @Embedded from annotation of Address
   Customer customer; // deduced @ManyToOne @JoinColumn
   // annotation required, otherwise would be deduced as @OneToMany
   @ManyToMany Roles[] roles;
}

@Embeddable // required for Embeddable
class Address {
   String zip;           // @Null
   String state;         // @Null
   string streetAddress; // @NotNull
}

// @Entity assumed since no @Embeddable annotation
class Customer {
   int id;     // @Generated primary key - from field name
   string name;// @NotNull
   Long flags; // @Null - because it's Long - not long
   LazyCollection!User users; // @OneToMany by default
   // annotation required, otherwise would be deduced as @ManyToOne
   // @JoinColumn is required on one of OneToOne sides
   @OneToOne @JoinColumn CustomerOptions customerOptions;
}

// @Entity assumed
class CustomerOptions {
   int id;
   // annotation required, otherwise would be deduced as @ManyToOne
   @OneToOne Customer customer;
}

// @Entity assumed since no @Embeddable annotation
class Role {
   int id;      // @Generated
   string name; // @NotNull
   // annotation required, otherwise would be deduced as @OneToMany
   @ManyToMany LazyCollection!User users;
}

Aliases added, to simple put uppercase Long instead of Nullable!long in code:
alias Nullable!byte Byte;
alias Nullable!ubyte Ubyte;
alias Nullable!short Short;
alias Nullable!ushort Ushort;
alias Nullable!int Int;
alias Nullable!uint Uint;
alias Nullable!long Long;
alias Nullable!ulong Ulong;
alias Nullable!float Float;
alias Nullable!double Double;
alias Nullable!DateTime NullableDateTime;
alias Nullable!Date NullableDate;
alias Nullable!TimeOfDay NullableTimeOfDay;

String (uppercase nullable version of string) is defined as struct wrapper around string field, with interface similar to Nullable!
Looks ugly, but I tried `typedef string String`, but it is deprecated; `alias string String` cannot be distinguished from just string. How to define String better? Is there a good way to define String to be compatible with string, but with the ability to distinguish between string and String in compile time?

April 05, 2013
On Friday, 5 April 2013 at 07:32:55 UTC, Vadim Lopatin wrote:
> Looks ugly, but I tried `typedef string String`, but it is deprecated; `alias string String` cannot be distinguished from just string. How to define String better? Is there a good way to define String to be compatible with string, but with the ability to distinguish between string and String in compile time?

Something like this : http://dpaste.1azy.net/ad013e4ef ?
April 05, 2013
On 2013-04-05 09:32, Vadim Lopatin wrote:

> Implemented changes for better convention-over-configuration:
> - If no annotations on class level, @Entity is assumed.
> - No required annotation for simple properties. Nullability is deduced
> from data type
> - @Embedded annotation is not needed anymore - it's deduced from field's
> class @Embeddable annotation
> - If no key field annotations specified in class (@Id, @Generated,
> @Generator) - property named "id" (if any) is considered to be a
> @Generated primary key.
> - For Object fields @ManyToOne is applied by default
> - For Object[] or LazyCollection!Object @OneToMany is applied by default
> - @OneToOne and @ManyToOne are required, since cannot be deduced
>
> Following declarations are valid (comments describe ):
>
> // @Entity assumed since no @Embeddable annotation
> class User {
>     long id;         // @Generated deduced from field name
>     string name;     // deduced @NotNull
>     Address address; // deduced @Embedded from annotation of Address
>     Customer customer; // deduced @ManyToOne @JoinColumn
>     // annotation required, otherwise would be deduced as @OneToMany
>     @ManyToMany Roles[] roles;
> }
>
> @Embeddable // required for Embeddable
> class Address {
>     String zip;           // @Null
>     String state;         // @Null
>     string streetAddress; // @NotNull
> }
>
> // @Entity assumed since no @Embeddable annotation
> class Customer {
>     int id;     // @Generated primary key - from field name
>     string name;// @NotNull
>     Long flags; // @Null - because it's Long - not long
>     LazyCollection!User users; // @OneToMany by default
>     // annotation required, otherwise would be deduced as @ManyToOne
>     // @JoinColumn is required on one of OneToOne sides
>     @OneToOne @JoinColumn CustomerOptions customerOptions;
> }
>
> // @Entity assumed
> class CustomerOptions {
>     int id;
>     // annotation required, otherwise would be deduced as @ManyToOne
>     @OneToOne Customer customer;
> }
>
> // @Entity assumed since no @Embeddable annotation
> class Role {
>     int id;      // @Generated
>     string name; // @NotNull
>     // annotation required, otherwise would be deduced as @OneToMany
>     @ManyToMany LazyCollection!User users;
> }

> String (uppercase nullable version of string) is defined as struct
> wrapper around string field, with interface similar to Nullable!
> Looks ugly, but I tried `typedef string String`, but it is deprecated;
> `alias string String` cannot be distinguished from just string. How to
> define String better? Is there a good way to define String to be
> compatible with string, but with the ability to distinguish between
> string and String in compile time?

Why won't Nullable!(string) String work?

Looks much better know. I'm wondering though, if there need to be a way to indicate a regular instance variable that isn't a column.

-- 
/Jacob Carlborg
April 05, 2013
On Friday, 5 April 2013 at 08:53:56 UTC, Jacob Carlborg wrote:
> Why won't Nullable!(string) String work?

It's to reduce field size (eliminate unnecessary bool field from Nullable!, but it's easy to support both cases.

> Looks much better know. I'm wondering though, if there need to be a way to indicate a regular instance variable that isn't a column.

1) Any private, protected, package members are not columns.
2) @Transient annotation may be applied to public member to say that it shouln't be persisted (like in Java)
April 05, 2013
On Friday, 5 April 2013 at 07:57:37 UTC, Dicebot wrote:
> On Friday, 5 April 2013 at 07:32:55 UTC, Vadim Lopatin wrote:
>> Looks ugly, but I tried `typedef string String`, but it is deprecated; `alias string String` cannot be distinguished from just string. How to define String better? Is there a good way to define String to be compatible with string, but with the ability to distinguish between string and String in compile time?
>
> Something like this : http://dpaste.1azy.net/ad013e4ef ?

It's as I have already implemented it. http://dpaste.1azy.net/a0393ce23
April 05, 2013
On Friday, 5 April 2013 at 09:26:30 UTC, Vadim Lopatin wrote:
> On Friday, 5 April 2013 at 07:57:37 UTC, Dicebot wrote:
>> On Friday, 5 April 2013 at 07:32:55 UTC, Vadim Lopatin wrote:
>>> Looks ugly, but I tried `typedef string String`, but it is deprecated; `alias string String` cannot be distinguished from just string. How to define String better? Is there a good way to define String to be compatible with string, but with the ability to distinguish between string and String in compile time?
>>
>> Something like this : http://dpaste.1azy.net/ad013e4ef ?
>
> It's as I have already implemented it. http://dpaste.1azy.net/a0393ce23

Why do you redefine constructor (it does exactly the same what default one) and prefer getter over raw alias this (thus adding necessity for opAssign)? Other than that looks pretty adequate match to desired behavior.
April 05, 2013
On Friday, 5 April 2013 at 09:22:17 UTC, Vadim Lopatin wrote:
> On Friday, 5 April 2013 at 08:53:56 UTC, Jacob Carlborg wrote:
>> Why won't Nullable!(string) String work?
>
> It's to reduce field size (eliminate unnecessary bool field from Nullable!, but it's easy to support both cases.
>
>> Looks much better know. I'm wondering though, if there need to be a way to indicate a regular instance variable that isn't a column.
>
> 1) Any private, protected, package members are not columns.
> 2) @Transient annotation may be applied to public member to say that it shouln't be persisted (like in Java)

Submitted fix to support @Transient.
It can be used on class level as well.

Currently, if module is passed to metadata extractor, only classes which have at least one HibernateD annotation are being imported.
Alternative is to import all classes, skipping only ones marked with @Transient.
Which way is better?