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