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