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 }