This is an automated email from the ASF dual-hosted git repository.
doebele pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/empire-db.git
The following commit(s) were added to refs/heads/master by this push:
new 6d67cf8 EMPIREDB-362 RollbackHandler fix and SampleAdv improvement
6d67cf8 is described below
commit 6d67cf8d9c1e9b5e1961092f461d1566795dcfa7
Author: Rainer Döbele <[email protected]>
AuthorDate: Sun Feb 20 23:16:13 2022 +0100
EMPIREDB-362 RollbackHandler fix and SampleAdv improvement
---
.../empire/samples/db/advanced/SampleAdvApp.java | 449 ++++++++-------------
.../empire/samples/db/advanced/db/CarSalesDB.java | 8 +-
.../empire-db-example-vue/readme.txt | 14 +-
.../java/org/apache/empire/db/DBColumnExpr.java | 22 +-
.../java/org/apache/empire/db/DBRecordBase.java | 26 +-
.../main/java/org/apache/empire/db/DBTable.java | 22 +-
.../empire/db/exceptions/RecordException.java | 2 +-
7 files changed, 232 insertions(+), 311 deletions(-)
diff --git
a/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/SampleAdvApp.java
b/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/SampleAdvApp.java
index c6413ac..1f1a993 100644
---
a/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/SampleAdvApp.java
+++
b/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/SampleAdvApp.java
@@ -24,8 +24,6 @@ import java.math.RoundingMode;
import java.sql.Connection;
import java.sql.DriverManager;
import java.time.LocalDate;
-import java.util.Date;
-import java.util.HashMap;
import java.util.List;
import org.apache.empire.commons.ObjectUtils;
@@ -43,6 +41,7 @@ import org.apache.empire.db.DBRecord;
import org.apache.empire.db.DBSQLScript;
import org.apache.empire.db.DBTableColumn;
import org.apache.empire.db.exceptions.ConstraintViolationException;
+import org.apache.empire.db.exceptions.RecordUpdateFailedException;
import org.apache.empire.db.exceptions.StatementFailedException;
import org.apache.empire.db.expr.compare.DBCompareExpr;
import org.apache.empire.dbms.DBMSHandler;
@@ -122,7 +121,7 @@ public class SampleAdvApp
context = new SampleContext(carSales, dbms, conn);
// set optional context features
context.setPreparedStatementsEnabled(false);
- context.setRollbackHandlingEnabled(true);
+ context.setRollbackHandlingEnabled(false);
// STEP 3: Open Database (and create if not existing)
System.out.println("*** Step 3: openDatabase() ***");
@@ -134,11 +133,28 @@ public class SampleAdvApp
insertSalesUsingBatch();
context.commit();
}
+
// do simple stuff
- // simpleQueryDemo();
- // simpleUpdateDemo();
- // queryViewDemo();
+ simpleQueryDemo();
+ simpleUpdateDemo();
+ queryViewDemo();
paramQueryDemo();
+
+ // Remember RollbackHandling
+ boolean prevRBHandling = context.isRollbackHandlingEnabled();
+ try {
+ // commit pending operations (just to be sure)
+ context.commit();
+ // run transaction demo
+ transactionDemo();
+ } finally {
+ context.setRollbackHandlingEnabled(prevRBHandling);
+ }
+
+ cascadeDeleteDemo();
+
+ ddlDemo("Beadles Volkswagen", "www.group1auto.co.uk",
"https://www.group1auto.co.uk/volkswagen/locations/beadles-volkswagen-dartford");
+
/*
// STEP 5: Clear Database (Delete all records)
@@ -350,7 +366,17 @@ public class SampleAdvApp
private int salesCount;
private BigDecimal avgSalesPrice;
private BigDecimal priceDifference;
-
+
+ /**
+ * Fields constructor for QueryResult
+ * Must match the SELECT phrase and will be used by queryBeanList()
+ * @param brand
+ * @param model
+ * @param basePrice
+ * @param salesCount
+ * @param avgSalesPrice
+ * @param priceDifference
+ */
public QueryResult(String brand, String model, BigDecimal basePrice
, int salesCount, BigDecimal avgSalesPrice,
BigDecimal priceDifference)
{
@@ -623,131 +649,6 @@ public class SampleAdvApp
}
/**
- * <PRE>
- * Empties all Tables.
- * </PRE>
- */
- private void clearDatabase()
- {
- DBCommand cmd = context.createCommand();
- // Delete all Employee Department History records
- context.executeDelete(T_EDH, cmd);
- // Delete all Employees (no constraints)
- context.executeDelete(T_EMP, cmd);
- // Delete all Departments (no constraints)
- context.executeDelete(T_DEP, cmd);
- }
-
- /**
- * <PRE>
- * Insert a Department into the Departments table.
- * </PRE>
- */
- private int insertDepartment(String departmentName, String businessUnit)
- {
- // Insert a Department
- DBRecord rec = new DBRecord(context, T_DEP);
- rec.create();
- rec.set(T_DEP.C_NAME, departmentName);
- rec.set(T_DEP.C_BUSINESS_UNIT, businessUnit);
- rec.update();
- // Return Department ID
- return rec.getInt(T_DEP.C_DEPARTMENT_ID);
- }
-
- /**
- * <PRE>
- * Inserts an Employee into the Employees table.
- * </PRE>
- */
- private int insertEmployee(String firstName, String lastName, String
gender)
- {
- // Insert an Employee
- DBRecord rec = new DBRecord(context, T_EMP);
- rec.create();
- rec.set(T_EMP.C_FIRSTNAME, firstName);
- rec.set(T_EMP.C_LASTNAME, lastName);
- rec.set(T_EMP.C_GENDER, gender);
- rec.update();
- // Return Employee ID
- return rec.getInt(T_EMP.C_EMPLOYEE_ID);
- }
-
- /**
- * <PRE>
- * Inserts an Employee into the Employees table.
- * </PRE>
- */
- private void insertEmpDepHistory(DBSQLScript script, int employeeId, int
departmentId, Date dateFrom)
- {
- // Insert an Employee
- /*
- DBRecord rec = new DBRecord(context);
- rec.create(T_EDH);
- rec.setValue(T_EDH.C_EMPLOYEE_ID, employeeId);
- rec.setValue(T_EDH.C_DEPARTMENT_ID, departmentId);
- rec.setValue(T_EDH.C_DATE_FROM, dateFrom);
- rec.update();
- */
- DBCommand cmd = context.createCommand();
- cmd.set(T_EDH.C_EMPLOYEE_ID.to(employeeId));
- cmd.set(T_EDH.C_DEPARTMENT_ID.to(departmentId));
- cmd.set(T_EDH.C_DATE_FROM.to(dateFrom));
- // Add to script for batch execution
- script.addInsert(cmd);
- }
-
- /* This procedure demonstrates the use of command parameter for prepared
statements */
- private void commandParamsSample(int idProdDep, int idDevDep)
- {
- // create a command
- DBCommand cmd = context.createCommand();
- // Create cmd parameters
- DBCmdParam curDepParam = cmd.addParam(); // Current Department
- DBCmdParam genderParam = cmd.addParam(); // Gender ('M' or 'F')
- // Define the query
- cmd.select(T_EMP.C_FULLNAME);
- cmd.join (T_EMP.C_EMPLOYEE_ID, db.V_EMPLOYEE_INFO.C_EMPLOYEE_ID);
- cmd.where (T_EMP.C_GENDER.is(genderParam));
- cmd.where (db.V_EMPLOYEE_INFO.C_CURRENT_DEP_ID.is(curDepParam));
-
- System.out.println("Perfoming two queries using a the same command
with different parameter values.");
-
- DBReader r = new DBReader(context);
- try {
- // Query all females currently working in the Production department
- System.out.println("1. Query all females currently working in the
production department");
- // Set command parameter values
- genderParam.setValue('F'); // set gender to female
- curDepParam.setValue(idProdDep); // set department id to
production department
- // Open reader using a prepared statement (due to command
parameters!)
- r.open(cmd);
- // print all results
- System.out.println("Females working in the production department
are:");
- while (r.moveNext())
- System.out.println(" " + r.getString(T_EMP.C_FULLNAME));
- r.close();
-
- // Second query
- // Now query all males currently working in the development
department
- System.out.println("2. Query all males currently working in the
development department");
- // Set command parameter values
- genderParam.setValue('M'); // set gender to female
- curDepParam.setValue(idDevDep); // set department id to production
department
- // Open reader using a prepared statement (due to command
parameters!)
- r.open(cmd);
- // print all results
- System.out.println("Males currently working in the development
department are:");
- while (r.moveNext())
- System.out.println(" " + r.getString(T_EMP.C_FULLNAME));
-
- } finally {
- r.close();
- }
-
- }
-
- /**
* This function performs a query to select non-retired employees,<BR>
* then it calculates a checksum for every record<BR>
* and writes that checksum back to the database.<BR>
@@ -810,78 +711,50 @@ public class SampleAdvApp
}
return sum;
}
-
- private HashMap<Integer, DBRecord> bulkReadRecords(Connection conn)
- {
- // Define the query
- DBCommand cmd = context.createCommand();
- // Select required columns
- cmd.select(T_EMP.getColumns());
- // Set Constraints
- cmd.where(T_EMP.C_RETIRED.is(false));
-
- // Query Records and print output
- DBReader reader = new DBReader(context);
- try
- { // Open Reader
- System.out.println("Running Query:");
- System.out.println(cmd.getSelect());
- reader.open(cmd);
- // Print output
- HashMap<Integer, DBRecord> employeeMap = new HashMap<Integer,
DBRecord>();
- while (reader.moveNext())
- {
- DBRecord rec = new DBRecord(context, T_EMP);
- reader.initRecord(rec);
- employeeMap.put(reader.getInt(T_EMP.C_EMPLOYEE_ID), rec);
- }
- return employeeMap;
-
- } finally
- { // always close Reader
- reader.close();
- }
- }
/**
* This method demonstrates how to add, modify and delete a database
column.<BR>
* This function demonstrates the use of the {@link
DBMSHandler#getDDLScript(org.apache.empire.db.DDLActionType,
org.apache.empire.db.DBObject, DBSQLScript)}<BR>
*
*/
- private void ddlSample(int idTestPerson)
+ private void ddlDemo(String dealerName, String websiteDomain, String
websiteUrl)
{
+ // create shortcuts
+ DBMSHandler dbms = context.getDbms();
+ CarSalesDB.Dealer DEALER = carSales.DEALER;
+
// First, add a new column to the Table object
- DBTableColumn C_FOO = db.T_EMPLOYEES.addColumn("FOO",
DataType.VARCHAR, 20, false);
+ DBTableColumn WEBSITE = DEALER.addColumn("WEBSITE", DataType.VARCHAR,
20, false);
// Now create the corresponding DDL statement
- System.out.println("Creating new column named FOO as varchar(20) for
the EMPLOYEES table:");
+ log.info("Create new column named WEBSITE as varchar(20) for the
DEALER table");
DBSQLScript script = new DBSQLScript(context);
- db.getDbms().getDDLScript(DDLActionType.CREATE, C_FOO, script);
+ dbms.getDDLScript(DDLActionType.CREATE, WEBSITE, script);
script.executeAll();
- // Now load a record from that table and set the value for foo
- System.out.println("Changing the value for the FOO field of a
particular employee:");
- DBRecord rec = new DBRecord(context, db.T_EMPLOYEES);
- rec.read(idTestPerson);
- rec.set(C_FOO, "Hello World");
+ // Now load a record from that table and set the value for the website
+ log.info("Set the value for the WEBSITE field for dealer \"{}\"",
dealerName);
+ DealerRecord rec = new DealerRecord(context);
+ rec.read(DEALER.COMPANY_NAME.is(dealerName));
+ rec.set (WEBSITE, websiteDomain);
rec.update();
- // Now extend the size of the field from 20 to 40 characters
- System.out.println("Extending size of column FOO to 40 characters:");
- C_FOO.setSize(40);
+ // Now extend the size of the field from 40 to 80 characters
+ log.info("Extend the size of column WEBSITE from 20 to 80 characters");
+ WEBSITE.setSize(80);
script.clear();
- db.getDbms().getDDLScript(DDLActionType.ALTER, C_FOO, script);
+ dbms.getDDLScript(DDLActionType.ALTER, WEBSITE, script);
script.executeAll();
// Now set a longer value for the record
- System.out.println("Changing the value for the FOO field for the above
employee to a longer string:");
- rec.set(C_FOO, "This is a very long field value!");
+ log.info("Change the value for the WEBSITE to a longer string \"{}\"",
websiteUrl);
+ rec.set(WEBSITE, websiteUrl);
rec.update();
// Finally, drop the column again
- System.out.println("Dropping the FOO column from the employee table:");
+ log.info("Drop the WEBSITE column from the DEALER table:");
script.clear();
- db.getDbms().getDDLScript(DDLActionType.DROP, C_FOO, script);
+ dbms.getDDLScript(DDLActionType.DROP, WEBSITE, script);
script.executeAll();
}
@@ -944,114 +817,118 @@ public class SampleAdvApp
* testTransactionCreate
* @param context
* @param idDep
- *
- private int testTransactionCreate(long idDep)
+ */
+ private void transactionDemo()
{
- // Shortcut for convenience
- SampleDB.Employees EMP = db.EMPLOYEES;
+ // Set RollbackHandlingEnabled to false if you want to play with fire!
+ // Note: You must set the RollbackHandling flag before creating a
Record instance
+ context.setRollbackHandlingEnabled(true);
- DBRecord rec = new DBRecord(context, EMP);
- rec.create();
- rec.set(EMP.FIRSTNAME, "Foo");
- rec.set(EMP.LASTNAME, "Manchoo");
- rec.set(EMP.GENDER, Gender.M);
- rec.set(EMP.DEPARTMENT_ID, idDep);
- rec.update();
- log.info("Timestamp {}", rec.getString(EMP.UPDATE_TIMESTAMP));
+ // User a model record
+ CarSalesDB.Model MODEL = carSales.MODEL;
+ ModelRecord model = new ModelRecord(context);
- rec.set(EMP.FIRSTNAME, "Foo 2");
- rec.set(EMP.LASTNAME, "Manchu");
- rec.set(EMP.PHONE_NUMBER, "0815/4711");
- rec.update();
- log.info("Timestamp {}", rec.getString(EMP.UPDATE_TIMESTAMP));
+ /*
+ * Part 1
+ */
+
+ // Insert a new model
+ log.info("Insert a new Model");
+ model.create()
+ .set(MODEL.WMI , "WVW") // = Volkswagen
+ .set(MODEL.NAME , "ID.4")
+ .set(MODEL.CONFIG_NAME , "ID.4 Pro Performance 150 kW 77 kWh")
+ .set(MODEL.TRIM , "Pro")
+ .set(MODEL.ENGINE_TYPE , EngineType.E)
+ .set(MODEL.ENGINE_POWER , 204);
+ // State and timestampe before and after insert
+ log.debug("Record state={}, key={}, Timestamp={}", model.getState(),
model.getKey(), model.get(MODEL.UPDATE_TIMESTAMP));
+ model.update();
+ log.debug("Record state={}, key={}, Timestamp={}", model.getState(),
model.getKey(), model.get(MODEL.UPDATE_TIMESTAMP));
+
+ // Update even once again without committing
+ model.set(MODEL.BASE_PRICE, 44915);
+ model.update();
+ log.debug("Record state={}, key={}, Timestamp={}", model.getState(),
model.getKey(), model.get(MODEL.UPDATE_TIMESTAMP));
+ // now, do the rollback
+ log.info("Performing rollback");
context.rollback();
+ log.debug("Record state={}, key={}, Timestamp={}", model.getState(),
model.getKey(), model.get(MODEL.UPDATE_TIMESTAMP));
- rec.set(EMP.FIRSTNAME, "Dr. Foo");
- rec.update();
- log.info("Timestamp {}", rec.getString(EMP.UPDATE_TIMESTAMP));
+ log.info("Update Model again, even though its not in the database
because of the rollback, hence Model will be inserted again.");
+ log.info("This will fail, if Rollback handling is not enabled!");
+ try {
+ model.set(MODEL.BASE_PRICE, 44900); // Only to mark the record as
modified if RollbackHandling is disabled!
+ model.update();
+ } catch(RecordUpdateFailedException e) {
+ log.error("Model update failed since rollback handling was not
enabled for this context!", e);
+ return; // the rest will fail too
+ }
+ log.debug("Record state={}, key={}, Timestamp={}", model.getState(),
model.getKey(), model.get(MODEL.UPDATE_TIMESTAMP));
- rec.delete();
+ /*
+ * Part 2
+ */
+
+ // Delete the model
+ model.delete();
+ log.debug("Record state={}", model.getState());
+ log.info("Performing rollback again");
context.rollback();
+ log.debug("Record state={}, key={}, Timestamp={}", model.getState(),
model.getKey(), model.get(MODEL.UPDATE_TIMESTAMP));
- // insert final
- rec.update();
- log.info("Timestamp {}", rec.getString(EMP.UPDATE_TIMESTAMP));
+ // Final update
+ log.info("Update Model again, even though a delete was executed but
was not committed.");
+ log.info("This will once again lead to an insert as the insert was
still not committed");
+ log.info("This will also fail, if Rollback handling is not enabled!");
+ try {
+ model.update();
+ } catch(RecordUpdateFailedException e) {
+ log.error("Model update failed since rollback handling was not
enabled for this context!", e);
+ return; // the rest will fail too
+ }
+ log.debug("Record state={}, key={}, Timestamp={}", model.getState(),
model.getKey(), model.get(MODEL.UPDATE_TIMESTAMP));
- log.info("testTransactionCreate performed OK");
+ // Finally commit
+ log.info("Finally commit the transaction in order to finalize the
Model insert");
context.commit();
+ log.debug("Record state={}, key={}, Timestamp={}", model.getState(),
model.getKey(), model.get(MODEL.UPDATE_TIMESTAMP));
- return rec.getInt(EMP.ID);
- }
- */
-
- /**
- * @param context
- * @param idDep
- *
- private void testTransactionUpdate(long idEmp)
- {
- // Shortcut for convenience
- SampleDB.Employees EMP = db.EMPLOYEES;
-
- DBRecord rec = new DBRecord(context, EMP);
- rec.read(idEmp);
- rec.set(EMP.PHONE_NUMBER, null);
- rec.set(EMP.SALARY, "100.000");
- rec.update();
-
- log.info("Timestamp {}", rec.getString(EMP.UPDATE_TIMESTAMP));
-
- context.rollback();
-
- rec.set(EMP.PHONE_NUMBER, "07531-45716-0");
- rec.update();
-
- log.info("Timestamp {}", rec.getString(EMP.UPDATE_TIMESTAMP));
+ /*
+ * Part 3
+ */
- context.rollback();
-
- rec.update();
-
- log.info("Timestamp {}", rec.getString(EMP.UPDATE_TIMESTAMP));
- log.info("testTransactionUpdate performed OK");
- context.commit();
- }
- */
-
- /**
- * @param context
- * @param idDep
- *
- private void testTransactionDelete(long idEmp)
- {
- // Shortcut for convenience
- SampleDB.Employees T = db.EMPLOYEES;
-
- DBRecord rec = new DBRecord(context, T);
- rec.read(idEmp);
-
- // log.info("Timestamp {}", rec.getString(T.UPDATE_TIMESTAMP));
- // rec.set(T.SALARY, "100.001");
- // rec.update();
- // log.info("Timestamp {}", rec.getString(T.UPDATE_TIMESTAMP));
+ // Update example with two consecutive updates
+ log.info("Fist update will change the timestamp");
+ model.set(MODEL.BASE_PRICE, 44000);
+ model.update();
+ log.debug("Record state={}, key={}, Timestamp={}", model.getState(),
model.getKey(), model.get(MODEL.UPDATE_TIMESTAMP));
- rec.delete();
+ log.info("Second update will change the timestamp again");
+ model.set(MODEL.BASE_PRICE, 42660);
+ model.update();
+ log.debug("Record state={}, key={}, Timestamp={}", model.getState(),
model.getKey(), model.get(MODEL.UPDATE_TIMESTAMP));
+ log.info("Performing rollback for the previous two updates");
context.rollback();
-
- // DBCommand cmd = context.createCommand();
- // cmd.select(T.UPDATE_TIMESTAMP);
- // cmd.where (T.EMPLOYEE_ID.is(idEmp));
- // log.info("Timestamp {}", db.querySingleString(cmd,
context.getConnection()));
+ log.debug("Record state={}, key={}, Timestamp={}", model.getState(),
model.getKey(), model.get(MODEL.UPDATE_TIMESTAMP));
- rec.update();
+ log.info("Update Model again, even though the previous two updates
have been rolled back");
+ log.info("This will again fail, if Rollback handling is not enabled!");
+ try {
+ model.update();
+ } catch(RecordUpdateFailedException e) {
+ log.error("Model update failed since rollback handling was not
enabled for this context!", e);
+ }
+ log.debug("Record state={}, key={}, Timestamp={}", model.getState(),
model.getKey(), model.get(MODEL.UPDATE_TIMESTAMP));
- log.info("Transaction performed OK");
+ // But now delete the model again, so we can rerun the example later
+ model.delete();
+ context.commit();
}
- */
-
+
/**
* This function demonstrates cascaded deletes.
* See DBRelation.setOnDeleteAction()
@@ -1060,23 +937,35 @@ public class SampleAdvApp
* @param idDepartment the id of the department to delete
* @param conn the connection
*/
- private void deleteRecordSample(int idEmployee, int idDepartment)
+ private void cascadeDeleteDemo()
{
- context.commit();
- // Delete an employee
- // This statement is designed to succeed since cascaded deletes are
enabled for this relation.
- db.T_EMPLOYEES.deleteRecord(idEmployee, context);
- System.out.println("The employee has been sucessfully deleted");
+ // Read a brand record
+ BrandRecord brand = new BrandRecord(context);
+ brand.read(carSales.BRAND.WMI.is("WVW")); // = Volkswagen
+
+ // Read dealer record
+ DealerRecord dealer = new DealerRecord(context);
+ dealer.read(carSales.DEALER.COMPANY_NAME.is("Autorigoldi S.p.A."));
- // Delete a department
- // This statement is designed to fail since cascaded deletes are not
on!
try {
- db.T_DEPARTMENTS.deleteRecord(idDepartment, context);
+ // This delete is designed to succeed since cascaded deletes are
enabled for this relation.
+ // see DEALER_BRANDS and SALES foreign key definition in
CarSalesDB:
+ // DEALER_ID = addForeignKey("DEALER_ID", db.DEALER, true,
true ); // Delete Cascade on
+ log.info("Deleting DEALER expecting to succeed since relationship
to DEALER_BRANDS and SALES is cascading");
+ dealer.delete();
+
+ // This delete is designed to succeed since cascaded deletes are
enabled for this relation.
+ log.info("Deleting BRAND expecting to fail since relationship to
DEALER_BRANDS and MODEL is NOT cascading");
+ brand.delete();
+
} catch(ConstraintViolationException e) {
- System.out.println("Delete of department failed as expected due to
existing depending records.");
+ log.info("Delete operation failed due to existing depending
records.");
} catch(StatementFailedException e) {
// Oops, the driver threw a SQLException instead
- System.out.println("Delete of department failed as expected due to
existing depending records.");
+ log.info("Delete operation failed with SQLException {}",
e.getMessage());
+ } finally {
+ // we don't really want to do this
+ context.rollback();
}
}
diff --git
a/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/db/CarSalesDB.java
b/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/db/CarSalesDB.java
index 34f75e4..75e0eaa 100644
---
a/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/db/CarSalesDB.java
+++
b/empire-db-examples/empire-db-example-advanced/src/main/java/org/apache/empire/samples/db/advanced/db/CarSalesDB.java
@@ -202,8 +202,8 @@ public class CarSalesDB extends TDatabase<CarSalesDB>
super("DEALER_BRANDS", db);
// Key columns
- DEALER_ID = addForeignKey("DEALER_ID", db.DEALER, true);
- WMI = addForeignKey("WMI", db.BRAND, true);
+ DEALER_ID = addForeignKey("DEALER_ID", db.DEALER, true,
true ); // Delete Cascade on
+ WMI = addForeignKey("WMI", db.BRAND, true,
false); // Delete Cascade off
// Data columns
DEALERSHIP_TYPE = addColumn("DEALERSHIP_TYPE", DataType.CHAR,
1, true, DealershipType.class);
YEAR_BEGIN = addColumn("YEAR_BEGIN", DataType.DECIMAL,
4.0, false);
@@ -229,8 +229,8 @@ public class CarSalesDB extends TDatabase<CarSalesDB>
super("SALES", db);
// ID
- MODEL_ID = addForeignKey("MODEL_ID", db.MODEL, true);
- DEALER_ID = addForeignKey("DEALER_ID", db.DEALER, true);
+ MODEL_ID = addForeignKey("MODEL_ID", db.MODEL, true,
false); // Delete Cascade off
+ DEALER_ID = addForeignKey("DEALER_ID", db.DEALER, true, true
); // Delete Cascade on
YEAR = addColumn("YEAR", DataType.DECIMAL,
4.0, true);
MONTH = addColumn("MONTH", DataType.DECIMAL,
2.0, true);
CAR_COLOR = addColumn("CAR_COLOR", DataType.VARCHAR,
20, false);
diff --git a/empire-db-examples/empire-db-example-vue/readme.txt
b/empire-db-examples/empire-db-example-vue/readme.txt
index c5fc675..14c7e8d 100644
--- a/empire-db-examples/empire-db-example-vue/readme.txt
+++ b/empire-db-examples/empire-db-example-vue/readme.txt
@@ -19,12 +19,16 @@ In order to run the vue example please do the following:
1. Start the REST-Service via "Debug on Server" using Tomcat
-2. Go to the directory "src/main/vue" (or open in WebStorm)
+2. Browse to: http://localhost:8080/empvue
-3. Rename file "_eslintrc.js.bak" to ".eslintrc.js" (must start with .)
+In order to debug and develop the vue example please do the following:
-4. Run the command: npm install
+3. Go to the directory "src/main/vue" (or open in WebStorm)
-5. Run the command: npm run dev
+4. Rename file "_eslintrc.js.bak" to ".eslintrc.js" (must start with .)
-6. Open Url: http://localhost:8088/
+5. Run the command: npm install
+
+6. Run the command: npm run dev
+
+7. Open Url: http://localhost:8088/
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java
b/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java
index b0e97f6..9b9f65b 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java
@@ -160,11 +160,13 @@ public abstract class DBColumnExpr extends DBExpr
* @param name the attribute name
* @param value the value of the attribute
*/
- public synchronized void setAttribute(String name, Object value)
+ @SuppressWarnings("unchecked")
+ public synchronized <T extends DBColumnExpr> T setAttribute(String name,
Object value)
{
if (attributes== null)
attributes = new Attributes();
attributes.set(name, value);
+ return (T)this;
}
/**
@@ -190,9 +192,11 @@ public abstract class DBColumnExpr extends DBExpr
*
* @param options the list of options
*/
- public synchronized void setOptions(Options options)
+ @SuppressWarnings("unchecked")
+ public synchronized <T extends DBColumnExpr> T setOptions(Options options)
{
this.options = options;
+ return (T)this;
}
/**
@@ -212,9 +216,9 @@ public abstract class DBColumnExpr extends DBExpr
*
* @param title the column title
*/
- public final void setTitle(String title)
+ public <T extends DBColumnExpr> T setTitle(String title)
{
- setAttribute(DBCOLATTR_TITLE, title);
+ return setAttribute(DBCOLATTR_TITLE, title);
}
/**
@@ -236,9 +240,9 @@ public abstract class DBColumnExpr extends DBExpr
*
* @param controlType the column control type
*/
- public final void setControlType(String controlType)
+ public final <T extends DBColumnExpr> T setControlType(String controlType)
{
- setAttribute(DBCOLATTR_TYPE, controlType);
+ return setAttribute(DBCOLATTR_TYPE, controlType);
}
/**
@@ -249,7 +253,7 @@ public abstract class DBColumnExpr extends DBExpr
* @return the name of the bean property used to get and set values
*/
@Override
- public String getBeanPropertyName()
+ public synchronized String getBeanPropertyName()
{
if (beanPropertyName==null)
{ // Compute bean property name
@@ -295,9 +299,11 @@ public abstract class DBColumnExpr extends DBExpr
*
* @param propertyName
*/
- public void setBeanPropertyName(String propertyName)
+ @SuppressWarnings("unchecked")
+ public synchronized <T extends DBColumnExpr> T setBeanPropertyName(String
propertyName)
{
this.beanPropertyName = propertyName;
+ return (T)this;
}
/**
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java
b/empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java
index ced3404..83d47a2 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java
@@ -124,20 +124,26 @@ public abstract class DBRecordBase extends DBRecordData
implements Record, Clone
{
return; // not modified!
}
+ // Make sure we have a modified array
+ if (modified==null)
+ modified = new boolean[fields.length];
+ // special case Timestamp
+ DBRowSet rowset = record.getRowSet();
+ DBColumn tsColumn = record.getRowSet().getTimestampColumn();
// copy
for (int i=0; i<fields.length; i++)
- {
- if (fields[i]!= s.fields[i])
- fields[i] = s.fields[i];
- // not modified
- if (modified==null)
+ { // ignore timestamp and key columns
+ DBColumn column = record.getColumn(i);
+ if (column==tsColumn || rowset.isKeyColumn(column))
+ continue;
+ // copy modified fields
+ if (s.modified[i]==false)
continue;
- if (modified[i]==false && s.modified[i])
- modified[i] = s.modified[i];
+ // field was modified
+ fields[i] = s.fields[i];
+ if (modified!=null)
+ modified[i] = true;
}
- // check modified
- if (modified==null && s.modified!=null)
- modified = copy(s.modified);
}
@Override
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBTable.java
b/empire-db/src/main/java/org/apache/empire/db/DBTable.java
index 08242d6..a87b6e1 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBTable.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBTable.java
@@ -440,7 +440,7 @@ public class DBTable extends DBRowSet implements Cloneable
* @param options (optional) a set of allowed values for this column
* @return the new column
*/
- public DBTableColumn addForeignKey(String name, DBTable target, boolean
required, Options options)
+ public DBTableColumn addForeignKey(String name, DBTable target, boolean
required, Options options, DBCascadeAction cascadeAction)
{
// Check target: If null then Table has not been defined yet!
if (target==null)
@@ -457,7 +457,9 @@ public class DBTable extends DBRowSet implements Cloneable
DBTableColumn referenceColumn = addColumn(name, keyDataType,
keyCol.getSize(), required, options);
// Adapter foreign key
String fkName = getName() + "_" + name.replace("_ID", "_FK");
- db.addRelation(fkName, referenceColumn.referenceOn(keyCol));
+ DBRelation relation = db.addRelation(fkName,
referenceColumn.referenceOn(keyCol));
+ if (cascadeAction!=null)
+ relation.setOnDeleteAction(cascadeAction);
return referenceColumn;
}
@@ -467,11 +469,25 @@ public class DBTable extends DBRowSet implements Cloneable
* @param name the name of the new column
* @param target the table on which to reference
* @param required true if the value is required
+ * @param cascade whether or not to cascade deletes for this relation
+ * @return the new column
+ */
+ public final DBTableColumn addForeignKey(String name, DBTable target,
boolean required, boolean cascade)
+ {
+ return addForeignKey(name, target, required, null, (cascade ?
DBCascadeAction.CASCADE : DBCascadeAction.NONE));
+ }
+
+ /**
+ * Adds a new ForgeinKey table column the column list
+ * The foreign table must have a single column foreign key
+ * @param name the name of the new column
+ * @param target the table on which to reference
+ * @param required true if the value is required
* @return the new column
*/
public final DBTableColumn addForeignKey(String name, DBTable target,
boolean required)
{
- return addForeignKey(name, target, required, null);
+ return addForeignKey(name, target, required, false);
}
/**
diff --git
a/empire-db/src/main/java/org/apache/empire/db/exceptions/RecordException.java
b/empire-db/src/main/java/org/apache/empire/db/exceptions/RecordException.java
index 319c005..2c3fe9c 100644
---
a/empire-db/src/main/java/org/apache/empire/db/exceptions/RecordException.java
+++
b/empire-db/src/main/java/org/apache/empire/db/exceptions/RecordException.java
@@ -54,7 +54,7 @@ public abstract class RecordException extends EmpireException
protected static String keyToString(Object[] key)
{
- return (key==null ? "["+StringUtils.arrayToString(key, "|")+"]" :
"[]");
+ return (key!=null ? "["+StringUtils.arrayToString(key, "|")+"]" :
"[]");
}
protected static String entityName(EntityType entity)