001: package simpleorm.examples;
002:
003: import simpleorm.core.*; // .* OK, all classes prefixed with "S".
004:
005: /** <b>START HERE</b> -- this class provides basic examples of the
006: main SimpleORM features. It demonstrates simple record
007: manipulations including non-identifying foreign keys.<p>
008: */
009:
010: public class ADemo implements SConstants {
011:
012: public static void main(String[] argv) throws Exception {
013: TestUte.initializeTest(ADemo.class); // Look at this code.
014: try {
015: testInit();
016: deptTest();
017: empTest();
018: } finally {
019: SConnection.detachAndClose();
020: }
021: }
022:
023: /** Prepare for tests, Delete old data. */
024: static void testInit() throws Exception {
025: System.out.println("################ Init #################");
026: SConnection.begin();
027:
028: /// Delete any old data from a previous run.
029: TestUte.dropAllTables();
030:
031: /// Suppress FOREIGN KEY DDL for this example only, can cause problems on some DBs.
032: if (true)
033: SConnection.getConnection().setPropertyValue(
034: SFD_NO_FOREIGN_KEY);
035:
036: //SConnection.commit();
037: //SConnection.begin();
038:
039: /// Create the tables.
040: SConnection.rawUpdateDB(Department.meta.createTableSQL());
041:
042: SConnection.rawUpdateDB(Employee.meta.createTableSQL());
043:
044: SConnection.commit();
045: }
046:
047: /** Basic examples/tests not involving foreign keys. */
048: static void deptTest() throws Exception {
049: System.out
050: .println("################ deptTest #################");
051: SConnection.begin();
052:
053: /// Create some Departments using the SDataLoader
054: SDataLoader deptDL = new SDataLoader(Department.meta);
055:
056: deptDL
057: .insertRecords(new Object[][] {
058: { "100", "One00", "Count Pennies", "10000",
059: "200000" },
060: { "200", "Two00", "Be Happy", "20000", "300000" },
061: { "300", "Three00", "Enjoy Life", "30000",
062: "150000" } });
063:
064: /// Flush the records to the database and commit the transaction.
065: SConnection.commit();
066: SConnection.begin();
067:
068: /// Retrieve a Department and check that we have the right one.
069: String key = "100";
070: Department department = (Department) Department.meta
071: .mustFind(key);
072: assertTrue(department.getString(Department.NAME)
073: .equals("One00"));
074:
075: /// Query the same Department again. This does not query the database.
076: Department department2 = (Department) Department.meta
077: .find("100");
078: assertTrue(department == department2);
079:
080: /// Create a new, empty department and set some column values.
081: Department newDept = (Department) Department.meta.create("900");
082: newDept.setString(Department.NAME, "New900");
083: newDept.setString(Department.BUDGET, "90000");
084:
085: SConnection.dumpCache();
086: SConnection.flush(); // To the database
087: SConnection.dumpCache();
088:
089: /// At this point there should be three departments with > $10,000.
090: selectDepartments(20000 + 30000 + 90000);
091:
092: /// Rollback new 900 Department. Flush() does not mean commit.
093: SConnection.rollback();
094: SConnection.dumpCache();
095:
096: SConnection.begin();
097:
098: /// Delete Department 300.
099: /// findOrCreate will (temporarily) create record 300 if it did not exist.
100: Department delDept = (Department) Department.meta
101: .findOrCreate("300");
102: delDept.deleteRecord();
103:
104: SConnection.commit();
105: SConnection.begin();
106:
107: /// Check only one department left > $10,000.
108: selectDepartments(20000);
109:
110: SConnection.commit();
111: }
112:
113: /** Query all the departments with Budget > 10000 and check that the
114: total budget == total.*/
115: static void selectDepartments(int total) {
116:
117: int qbudget = 10000;
118:
119: /// Prepare and execute the query. The two queries are identical,
120: // but one uses raw SQL and the other uses the query builder.
121: SResultSet res = null;
122: if (true) { // Query interface style
123: res = Department.meta.newQuery().gt(Department.BUDGET,
124: SJSharp.newInteger(qbudget)).descending(
125: Department.NAME).execute();
126: } else { // Direct SQL Style
127: SPreparedStatement stmt = Department.meta.select(
128: "BUDGET > ?", "NAME DESC");
129: stmt.setInt(1, qbudget);
130: res = stmt.execute();
131: }
132:
133: /// loop through the results, adding up the budgets.
134: double totBudget = 0;
135: while (res.hasNext()) {
136: Department dept = (Department) res.getRecord();
137: double budget = dept.getDouble(Department.BUDGET);
138: totBudget += budget;
139: }
140:
141: /// Check that the total is what we expect.
142: assertTrue(totBudget == total);
143: }
144:
145: /**
146: Examples non identifying foreign key relationship
147: from Employee to Department, and from Employee to
148: Employee.Manager. */
149: static void empTest() { // Foreign Keys
150: System.out
151: .println("################ empTest #################");
152: SConnection.begin();
153:
154: /// Dump all the fields in the Employee record. Note that the
155: /// DEPT_ID is included even though it is not explicitly part of the
156: /// Employee record's definition.
157: System.out.println("Employee Fields "
158: + Employee.meta.allFieldsString());
159:
160: /// Create an Employee
161: SDataLoader empDL = new SDataLoader(Employee.meta);
162: Employee e100 = (Employee) empDL.insertRecord(new Object[] {
163: "100", "One00", "123 456 7890", "10000", "3", null,
164: null });
165:
166: /// Explicitily set the Department
167: Department d100 = (Department) Department.meta
168: .findOrCreate("100");
169: e100.setReference(e100.DEPARTMENT, d100);
170: // Compare allFields() with the concise toString() that just shows keys.
171: System.out.println("e100#" + e100.allFields());
172:
173: /// Create more Employees setting the Department using the DataLoader
174: Department d200 = (Department) Department.meta
175: .findOrCreate("200");
176: empDL.insertRecords(new Object[][] { // Twice should not cause grief
177: { "200", "Two00", "123 456 7890", "20000", "0",
178: d200, e100 },
179: { "300", "Three00", "123 456 7890", "30000",
180: "1", null, e100 } });
181:
182: SConnection.flush();
183:
184: Employee e300 = (Employee) Employee.meta.newQuery().eq(
185: Employee.NAME, "Three00").execute().getOnlyRecord();
186: assertTrue("123 456 7890".equals(e300.getString(e300.PHONE_NR)));
187:
188: SConnection.commit();
189: SConnection.begin();
190:
191: /// Check e100 record NOT valid after a commit()
192: /// (locks released so need to requery).
193: try {
194: e100.getString(Employee.NAME); // Error as e100 destroyed by commit.
195: throw new SException.Test("e100 not destroyed.");
196: } catch (SException.Error er) {
197: SLog.slog.message("Destroyed Record Message: " + er);
198: }
199:
200: /// Retrieve e100's Department.
201: Employee e100a = (Employee) Employee.meta.findOrCreate("100");
202: Department d100a = (Department) e100a
203: .getReference(e100a.DEPARTMENT);
204: assertTrue(d100a.getString(Department.NAME).equals("One00"));
205:
206: /// Attempt to pay e200 -ve is traped immediately.
207: Employee e200 = (Employee) Employee.meta.findOrCreate("200");
208: try {
209: e200.setDouble(e200.SALARY, -1);
210: throw new SException.Test("Negative Salary not detected.");
211: } catch (SValidationException ve) {
212: SLog.slog.message("Salary Negative message: "
213: + ve.getMessage());
214: }
215:
216: /// Attempt to pay e200 too much is detected at Commit/Flush time.
217: e200.setDouble(e200.SALARY, 500000);
218: try {
219: SConnection.commit();
220: throw new SException.Test("Big Salary not detected.");
221: } catch (SValidationException ve) {
222: SLog.slog.message("Big Salary message: "
223: + ve.getRecordInstance() + ve.getMessage());
224: SConnection.rollback();
225: }
226:
227: }
228:
229: static void assertTrue(boolean cond) {
230: TestUte.assertTrue(cond);
231: }
232: }
|