1 module htestmain;
2 
3 import std.stdio;
4 import std..string;
5 import std.conv;
6 import dstruct.core;
7 import std.traits;
8 
9 // Annotations of entity classes
10 @Table("usertests")
11 class User
12 {
13     long id;
14     string name;
15     int some_field_with_underscore;
16     @ManyToMany // cannot be inferred, requires annotation
17     LazyCollection!Role roles;
18     //@ManyToOne
19     MyGroup group;
20 
21     @OneToMany Address[] addresses;
22 
23     Asset[] assets;
24 
25     override string toString()
26     {
27         return format("{id:%s, name:%s, roles:%s, group:%s}", id, name, roles, group);
28     }
29 }
30 
31 class Role
32 {
33     int id;
34     string name;
35     @ManyToMany // w/o this annotation will be OneToMany by convention
36     LazyCollection!User users;
37 
38     override string toString()
39     {
40         return format("{id:%s, name:%s}", id, name);
41     }
42 }
43 
44 class Address
45 {
46     @Generated @Id int id;
47     User user;
48     string street;
49     string town;
50     string country;
51 
52     override string toString()
53     {
54         return format("{id:%s, user:%s, street:%s, town:%s, country:%s}", id,
55                 user, street, town, country);
56     }
57 }
58 
59 class Asset
60 {
61     @Generated @Id int id;
62     User user;
63     string name;
64 }
65 
66 @Entity class MyGroup
67 {
68     long id;
69     string name;
70     @OneToMany LazyCollection!User users;
71 
72     override string toString()
73     {
74         return format("{id:%s, name:%s}", id, name);
75     }
76 }
77 
78 void testHibernate()
79 {
80     version (USE_SQLITE)
81     {
82         import dstruct.ddbc.drivers.sqliteddbc;
83 
84         SQLITEDriver driver = new SQLITEDriver();
85         string[string] params;
86         DataSource ds = new ConnectionPoolDataSourceImpl(driver, "dstruct_tests.db", params);
87         Dialect dialect = new SQLiteDialect();
88     }
89     else version (USE_PGSQL)
90     {
91         import dstruct.ddbc.drivers.pgsqlddbc;
92         writeln("Using postgres for tests....");
93 
94         string url = PGSQLDriver.generateUrl( "127.0.0.1", 5432, "dstruct_tests" );
95 
96         string[string] params;
97         params["user"] = "dstruct";
98         params["password"] = "dstruct";
99         params["ssl"] = "true";
100         PGSQLDriver driver = new PGSQLDriver();
101         DataSource ds = new ConnectionPoolDataSourceImpl(driver,url, params);
102         Dialect dialect = new PGSQLDialect();
103     }
104 
105     // create metadata from annotations
106     writeln("Creating schema from class list");
107     EntityMetaData schema = new SchemaInfoImpl!(User, Role, Address, Asset, MyGroup);
108     writeln("Creating schema from module list");
109     EntityMetaData schema2 = new SchemaInfoImpl!(htestmain);
110 
111     writeln("Creating session factory");
112     // create session factory
113     SessionFactory factory = new SessionFactoryImpl(schema, dialect, ds);
114     scope(exit) factory.close();
115 
116     writeln("Creating DB schema");
117     DBInfo db = factory.getDBMetaData();
118     {
119         Connection conn = ds.getConnection();
120         scope(exit) conn.close();
121         db.updateDBSchema(conn, true, true);
122     }
123 
124     // create session
125     Session sess = factory.openSession();
126     scope(exit) sess.close();
127 
128     // use session to access DB
129 
130     writeln("Querying empty DB");
131     Query q = sess.createQuery("FROM User ORDER BY name");
132     User[] list = q.list!User();
133     writeln("Result size is " ~ to!string(list.length));
134 
135     // create sample data
136     writeln("Creating sample schema");
137     MyGroup grp1 = new MyGroup();
138     grp1.name = "Group-1";
139     MyGroup grp2 = new MyGroup();
140     grp2.name = "Group-2";
141     MyGroup grp3 = new MyGroup();
142     grp3.name = "Group-3";
143     //
144     Role r10 = new Role();
145     r10.name = "role10";
146     Role r11 = new Role();
147     r11.name = "role11";
148 
149     // create a user called Alex with an address and an asset
150     User u10 = new User();
151     u10.name = "Alex";
152     u10.roles = [r10, r11];
153     u10.group = grp3;
154     auto address = new Address();
155     address.street = "Some Street";
156     address.town = "Big Town";
157     address.country = "Alaska";
158     address.user = u10;
159     writefln("Saving Address: %s", address);
160     sess.save(address);
161 
162     u10.addresses = [address];
163     auto asset = new Asset();
164     asset.name = "Something Precious";
165     asset.user = u10;
166     writefln("Saving Asset: %s", asset);
167     sess.save(asset);
168     u10.assets = [asset];
169 
170     User u12 = new User();
171     u12.name = "Arjan";
172     u12.roles = [r10, r11];
173     u12.group = grp2;
174 
175     User u13 = new User();
176     u13.name = "Wessel";
177     u13.roles = [r10, r11];
178     u13.group = grp2;
179 
180     writeln("saving group 1-2-3" );
181     sess.save( grp1 );
182     sess.save( grp2 );
183     sess.save( grp3 );
184 
185     writeln("Saving Role r10: " ~ r10.name);
186     sess.save(r10);
187 
188     writeln("Saving Role r11: " ~ r11.name);
189     sess.save(r11);
190 
191     writeln("Saving User u10: " ~ u10.name);
192     sess.save(u10);
193 
194     writeln("Saving User u12: " ~ u12.name);
195     sess.save(u12);
196 
197     writeln("Saving User u13: " ~ u13.name);
198     sess.save(u13);
199 
200     writeln("Loading User");
201     // load and check data
202     auto qresult = sess.createQuery("FROM User WHERE name=:Name and some_field_with_underscore != 42").setParameter("Name", "Alex");
203     writefln( "query result: %s", qresult.listRows() );
204     User u11 = qresult.uniqueResult!User();
205     //User u11 = sess.createQuery("FROM User WHERE name=:Name and some_field_with_underscore != 42").setParameter("Name", "Alex").uniqueResult!User();
206     writefln("Checking User 11 : %s", u11);
207     assert(u11.roles.length == 2);
208     assert(u11.roles[0].name == "role10" || u11.roles.get()[0].name == "role11");
209     assert(u11.roles[1].name == "role10" || u11.roles.get()[1].name == "role11");
210     assert(u11.roles[0].users.length == 3);
211     assert(u11.roles[0].users[0] == u10);
212 
213     assert(u11.addresses.length == 1);
214     assert(u11.addresses[0].street == "Some Street");
215     assert(u11.addresses[0].town == "Big Town");
216     assert(u11.addresses[0].country == "Alaska");
217 
218     assert(u11.assets.length == 1);
219     assert(u11.assets[0].name == "Something Precious");
220 
221     // selecting all from address table should return a row that joins to the user table
222     auto allAddresses = sess.createQuery("FROM Address").list!Address();
223     assert(allAddresses.length == 1);
224     writefln("Found address : %s", allAddresses[0]);
225     assert(allAddresses[0].street == "Some Street");
226     assert(allAddresses[0].user == u11);
227 
228     // selecting all from asset table should return a row that joins to the user table
229     auto allAssets = sess.createQuery("FROM Asset").list!Asset();
230     assert(allAssets.length == 1);
231     writefln("Found asset : %s", allAssets[0]);
232     assert(allAssets[0].name == "Something Precious");
233     assert(allAssets[0].user == u11);
234 
235     // now test something else
236     writeln("Test retrieving users by group... (ManyToOne relationship)");
237     auto qUsersByGroup = sess.createQuery("FROM User WHERE group=:group_id").setParameter("group_id", grp2.id);
238     User[] usersByGroup = qUsersByGroup.list!User();
239     assert(usersByGroup.length == 2); // user 2 and user 2
240 
241     //writeln("Removing User");
242     // remove reference
243     //std.algorithm.remove(u11.roles.get(), 0);
244     //sess.update(u11);
245 
246     // remove entity
247     //sess.remove(u11);
248 }
249 
250 void main()
251 {
252     testHibernate();
253 }