blob: 176220cf3c04a78ce3440a6ce8e9eb9c9beb9525 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.empire.samples.db.advanced;
import java.io.Serializable;
import java.math.BigDecimal;
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;
import org.apache.empire.commons.Options;
import org.apache.empire.commons.StringUtils;
import org.apache.empire.data.DataType;
import org.apache.empire.data.list.DataListEntry;
import org.apache.empire.db.DBCmdParam;
import org.apache.empire.db.DBColumnExpr;
import org.apache.empire.db.DBCommand;
import org.apache.empire.db.DBDDLGenerator.DDLActionType;
import org.apache.empire.db.DBQuery;
import org.apache.empire.db.DBReader;
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.StatementFailedException;
import org.apache.empire.dbms.DBMSHandler;
import org.apache.empire.samples.db.advanced.db.CarSalesDB;
import org.apache.empire.samples.db.advanced.db.CarSalesDB.DealershipType;
import org.apache.empire.samples.db.advanced.db.CarSalesDB.EngineType;
import org.apache.empire.samples.db.advanced.db.DealerSalesView;
import org.apache.empire.samples.db.advanced.records.BrandRecord;
import org.apache.empire.samples.db.advanced.records.DealerRecord;
import org.apache.empire.samples.db.advanced.records.ModelRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SampleAdvApp
{
// Logger
private static final Logger log = LoggerFactory.getLogger(SampleAdvApp.class);
private static SampleAdvConfig config = new SampleAdvConfig();
private final CarSalesDB carSales = new CarSalesDB();
private SampleContext context;
// Shortcuts
private final SampleAdvDB db = new SampleAdvDB();
private SampleAdvDB.Employees T_EMP = db.T_EMPLOYEES;
private SampleAdvDB.Departments T_DEP = db.T_DEPARTMENTS;
private SampleAdvDB.EmployeeDepartmentHistory T_EDH = db.T_EMP_DEP_HIST;
/**
* <PRE>
* This is the entry point of the Empire-DB Sample Application
* Please check the config.xml configuration file for Database and Connection settings.
* </PRE>
* @param args arguments
*/
public static void main(String[] args)
{
// Init Configuration
config.init((args.length > 0 ? args[0] : "config.xml" ));
// create the app
SampleAdvApp app = new SampleAdvApp();
try
{ // Run
log.info("Running DB Sample...");
app.run();
// Done
log.info("DB Sample finished successfully.");
} catch (Exception e) {
// Error
log.error("Running SampleApp failed with Exception" + e.toString(), e);
if (app.context!=null)
app.context.rollback();
} finally {
if (app.context!=null)
app.context.discard();
}
}
/**
* This method runs all the example code
*/
public void run()
{
// STEP 1: Get a JDBC Connection
System.out.println("*** Step 1: getJDBCConnection() ***");
Connection conn = getJDBCConnection();
// STEP 2: Choose a dbms
System.out.println("*** Step 2: getDatabaseProvider() ***");
DBMSHandler dbms = getDBMSHandler(config.getDatabaseProvider());
// STEP 2.2: Create a Context
context = new SampleContext(carSales, dbms, conn);
// set optional context features
context.setPreparedStatementsEnabled(false);
context.setRollbackHandlingEnabled(true);
// STEP 3: Open Database (and create if not existing)
System.out.println("*** Step 3: openDatabase() ***");
// db.open(context);
carSales.open(context);
if (carSales.wasCreated())
{ // newly created
populateDatabase();
insertSalesUsingBatch();
context.commit();
}
// do simple stuff
queryViewDemo();
simpleQueryDemo();
simpleUpdateDemo();
/*
// STEP 5: Clear Database (Delete all records)
System.out.println("*** Step 5: clearDatabase() ***");
clearDatabase();
// STEP 6: Insert Records
// Insert Departments
System.out.println("*** Step 6: inserting departments, employees and employee_department_history records ***");
int idDevDep = insertDepartment("Development", "ITTK");
int idProdDep = insertDepartment("Production", "ITTK");
int idSalDep = insertDepartment("Sales", "ITTK");
// Insert Employees
int idEmp1 = insertEmployee("Peter", "Sharp", "M");
int idEmp2 = insertEmployee("Fred", "Bloggs", "M");
int idEmp3 = insertEmployee("Emma", "White", "F");
// Insert History as batch
DBSQLScript batch = new DBSQLScript(context);
insertEmpDepHistory(batch, idEmp1, idDevDep, DateUtils.getDate(2007, 12, 1));
insertEmpDepHistory(batch, idEmp1, idProdDep, DateUtils.getDate(2008, 9, 1));
insertEmpDepHistory(batch, idEmp1, idSalDep, DateUtils.getDate(2009, 5, 15));
insertEmpDepHistory(batch, idEmp2, idSalDep, DateUtils.getDate(2006, 3, 1));
insertEmpDepHistory(batch, idEmp2, idDevDep, DateUtils.getDate(2008, 11, 15));
insertEmpDepHistory(batch, idEmp3, idDevDep, DateUtils.getDate(2006, 9, 15));
insertEmpDepHistory(batch, idEmp3, idSalDep, DateUtils.getDate(2007, 6, 1));
insertEmpDepHistory(batch, idEmp3, idProdDep, DateUtils.getDate(2008, 7, 31));
batch.executeBatch();
// commit
context.commit();
// STEP 7: read from Employee_Info_View
System.out.println("--------------------------------------------------------");
System.out.println("*** read from EMPLOYEE_INFO_VIEW ***");
DBCommand cmd = context.createCommand();
cmd.select (db.V_EMPLOYEE_INFO.getColumns());
cmd.orderBy(db.V_EMPLOYEE_INFO.C_NAME_AND_DEP);
printQueryResults(cmd);
// STEP 8: prepared Statement sample
System.out.println("--------------------------------------------------------");
System.out.println("*** commandParamsSample: shows how to use command parameters for the generation of prepared statements ***");
commandParamsSample(idProdDep, idDevDep);
// STEP 9: bulkReadRecords
System.out.println("--------------------------------------------------------");
System.out.println("*** bulkReadRecords: reads employee records into a hashmap, reads employee from hashmap and updates employee ***");
HashMap<Integer, DBRecord> employeeMap = bulkReadRecords(conn);
DBRecord rec = employeeMap.get(idEmp2);
rec.set(db.T_EMPLOYEES.C_SALUTATION, "Mr.");
rec.update();
// STEP 10: bulkProcessRecords
System.out.println("--------------------------------------------------------");
System.out.println("*** bulkProcessRecords: creates a checksum for every employee in the employees table ***");
bulkProcessRecords();
// STEP 11: querySample
System.out.println("--------------------------------------------------------");
System.out.println("*** querySample: shows how to use DBQuery class for subqueries and multi table records ***");
querySample(idEmp2);
// STEP 12: ddlSample
System.out.println("--------------------------------------------------------");
System.out.println("*** ddlSample: shows how to add a column at runtime and update a record with the added column ***");
if (db.getDbms() instanceof DBMSHandlerH2) {
log.info("As H2 does not support changing a table with a view defined we remove the view");
System.out.println("*** drop EMPLOYEE_INFO_VIEW ***");
DBSQLScript script = new DBSQLScript(context);
db.getDbms().getDDLScript(DDLActionType.DROP, db.V_EMPLOYEE_INFO, script);
script.executeAll();
}
ddlSample(idEmp2);
if (db.getDbms() instanceof DBMSHandlerH2) {
log.info("And put back the view");
System.out.println("*** create EMPLOYEE_INFO_VIEW ***");
DBSQLScript script = new DBSQLScript(context);
db.getDbms().getDDLScript(DDLActionType.CREATE, db.V_EMPLOYEE_INFO, script);
script.executeAll();
}
// STEP 13: delete records
System.out.println("--------------------------------------------------------");
System.out.println("*** deleteRecordSample: shows how to delete records (with and without cascade) ***");
deleteRecordSample(idEmp3, idSalDep);
*/
// Done
System.out.println("--------------------------------------------------------");
System.out.println("DB Sample Advanced finished successfully.");
}
public void populateDatabase()
{
// Add some brands
BrandRecord brandVW = (new BrandRecord(context)).insert("WVW", "Volkswagen", "Germany");
BrandRecord brandFord = (new BrandRecord(context)).insert("1F", "Ford", "USA");
BrandRecord brandTesla = (new BrandRecord(context)).insert("5YJ", "Tesla", "USA");
BrandRecord brandToy = (new BrandRecord(context)).insert("JT", "Toyota", "Japan");
// Add some models
ModelRecord model = new ModelRecord(context);
model.insert(brandVW, "Golf", "Golf Style 1,5 l TSI", "Style", EngineType.P, 130, 30970d);
model.insert(brandVW, "Golf", "Golf R-Line 2,0 l TSI 4MOTION","R-Line", EngineType.P, 190, 38650d);
model.insert(brandVW, "Tiguan", "Tiguan Life 1,5 l TSI", "Life", EngineType.P, 150, 32545d);
model.insert(brandVW, "Tiguan", "Tiguan Elegance 2,0 l TDI SCR","Elegance", EngineType.D, 150, 40845d);
model.insert(brandVW, "Tiguan", "Tiguan R-Line 1,4 l eHybrid", "R-Line", EngineType.H, 150, 48090d);
// Tesla
model.insert(brandTesla,"Model 3", "Model 3 LR", "Long Range", EngineType.E, 261, 45940d);
model.insert(brandTesla,"Model 3", "Model 3 Performance", "Performance", EngineType.E, 487, 53940d);
model.insert(brandTesla,"Model Y", "Model Y LR", "Long Range", EngineType.E, 345, 53940d);
model.insert(brandTesla,"Model Y", "Model Y Performance", "Performance", EngineType.E, 450, 58940d);
model.insert(brandTesla,"Model S", "Model S Plaid", "Plaid", EngineType.E, 1020,0d);
// Ford
model.insert(brandFord, "Mustang", "Mustang GT 5,0 l Ti-VCT V8", "GT", EngineType.P, 449, 54300d);
model.insert(brandFord, "Mustang", "Mustang Mach1 5,0 l Ti-VCT V8", "Mach1", EngineType.P, 460, 62800d);
// Toyota
model.insert(brandToy, "Prius", "Prius Hybrid 1,8-l-VVT-i", "Basis", EngineType.H, 122, 38000d);
model.insert(brandToy, "Supra", "GR Supra Pure 2,0 l Twin-Scroll Turbo","Pure", EngineType.P, 258, 49290d);
// Add some dealers
DealerRecord dealerDE = (new DealerRecord(context)).insert("Autozentrum Schmitz", "Munich", "Germany");
DealerRecord dealerUK = (new DealerRecord(context)).insert("Beadles Volkswagen", "Dartford", "United Kingdom");
DealerRecord dealerUS = (new DealerRecord(context)).insert("Auto Nation", "Los Angeles", "USA");
DealerRecord dealerFR = (new DealerRecord(context)).insert("Vauban Motors Argenteuil", "Paris", "France");
DealerRecord dealerIT = (new DealerRecord(context)).insert("Autorigoldi S.p.A.", "Milan", "Italy");
// Add brands to dealers
CarSalesDB.DealerBrands DB = carSales.DEALER_BRANDS;
DBRecord rec = new DBRecord(context, DB);
rec.create(DBRecord.key(dealerDE, brandTesla)).set(DB.DEALERSHIP_TYPE, DealershipType.B).update();
rec.create(DBRecord.key(dealerDE, brandVW)) .set(DB.DEALERSHIP_TYPE, DealershipType.U).update();
rec.create(DBRecord.key(dealerUK, brandVW)) .set(DB.DEALERSHIP_TYPE, DealershipType.B).update();
rec.create(DBRecord.key(dealerUK, brandFord)) .set(DB.DEALERSHIP_TYPE, DealershipType.I).update();
rec.create(DBRecord.key(dealerUS, brandFord)) .set(DB.DEALERSHIP_TYPE, DealershipType.B).update();
rec.create(DBRecord.key(dealerUS, brandTesla)).set(DB.DEALERSHIP_TYPE, DealershipType.I).update();
rec.create(DBRecord.key(dealerFR, brandToy)) .set(DB.DEALERSHIP_TYPE, DealershipType.B).update();
rec.create(DBRecord.key(dealerIT, brandToy)) .set(DB.DEALERSHIP_TYPE, DealershipType.G).update();
rec.create(DBRecord.key(dealerIT, brandVW)) .set(DB.DEALERSHIP_TYPE, DealershipType.B).update();
}
private void insertSalesUsingBatch()
{
CarSalesDB db = this.carSales;
DBSQLScript batch = new DBSQLScript(context);
// get list of all dealers
DBCommand cmd = context.createCommand();
cmd.select(db.DEALER.ID);
List<Long> dealerIdList = context.getUtils().querySimpleList(Long.class, cmd);
// get all models
cmd.clear();
cmd.select(db.MODEL.ID, db.MODEL.CONFIG_NAME, db.MODEL.BASE_PRICE); // select the ones we need (optional)
// no constraints on model
List<DataListEntry> modelList = context.getUtils().queryDataList(cmd);
for (DataListEntry model : modelList)
{
int count = generateRandomSales(batch, model, dealerIdList);
log.info("{} Sales added for Model {}", count, model.getString(db.MODEL.CONFIG_NAME));
}
// execute the batch
int count = batch.executeBatch();
log.info("{} Sales added with batch", count);
}
private int generateRandomSales(DBSQLScript batch, DataListEntry model, List<Long> dealerIdList)
{
CarSalesDB db = this.carSales;
BigDecimal price = model.getDecimal(db.MODEL.BASE_PRICE);
if (ObjectUtils.isEmpty(price))
return 0;
int count = 0;
int baseYear = LocalDate.now().getYear()-3;
DBCommand cmd = context.createCommand();
for (int i = (int)(Math.random()*99)+25; i>0; i--)
{
int dealIdx = (int)(Math.random()*dealerIdList.size());
int year = (int)(Math.random()*3)+baseYear;
int month = (int)(Math.random()*12)+1;
BigDecimal variation = new BigDecimal((Math.random()*200) - 100.0);
variation = variation.setScale(2, RoundingMode.HALF_UP);
cmd.set(db.SALES.MODEL_ID.to(model.getRecordId(db.MODEL)))
.set(db.SALES.DEALER_ID.to(dealerIdList.get(dealIdx)))
.set(db.SALES.YEAR.to(year))
.set(db.SALES.MONTH.to(month))
.set(db.SALES.PRICE.to(price.add(variation)));
// add to batch
batch.addInsert(cmd);
count++;
}
return count;
}
/**
* The result Bean for the query Example
* @author rainer
*/
public static class QueryResult implements Serializable
{
private static final long serialVersionUID = 1L;
private String brand;
private String model;
private BigDecimal basePrice;
private int salesCount;
private BigDecimal avgSalesPrice;
private BigDecimal priceDifference;
public QueryResult(String brand, String model, BigDecimal basePrice
, int salesCount, BigDecimal avgSalesPrice, BigDecimal priceDifference)
{
this.brand = brand;
this.model = model;
this.basePrice = basePrice;
this.salesCount = salesCount;
this.avgSalesPrice = avgSalesPrice;
this.priceDifference = priceDifference;
}
public String getBrand()
{
return brand;
}
public String getModel()
{
return model;
}
public BigDecimal getBasePrice()
{
return basePrice;
}
public int getSalesCount()
{
return salesCount;
}
public BigDecimal getAvgSalesPrice()
{
return avgSalesPrice;
}
public BigDecimal getPriceDifference()
{
return priceDifference;
}
}
public void simpleQueryDemo()
{
// shortcuts (for convenience)
CarSalesDB.Brand BRAND = carSales.BRAND;
CarSalesDB.Model MODEL = carSales.MODEL;
CarSalesDB.Sales SALES = carSales.SALES;
// create command
DBCommand cmd = context.createCommand()
.selectQualified(BRAND.NAME, MODEL.CONFIG_NAME)
.select (MODEL.BASE_PRICE)
.select (SALES.MODEL_ID.count(), SALES.PRICE.avg())
.select (SALES.PRICE.avg().minus(MODEL.BASE_PRICE.avg()).round(2))
.join (MODEL.WMI, BRAND.WMI)
.joinLeft(MODEL.ID, SALES.MODEL_ID, SALES.YEAR.is(2021)) // only year 2021
.where (MODEL.ENGINE_TYPE.in(EngineType.P, EngineType.H, EngineType.E)) // Petrol, Hybrid, Electric
.where (MODEL.BASE_PRICE.isGreaterThan(30000))
.groupBy (BRAND.NAME, MODEL.CONFIG_NAME, MODEL.BASE_PRICE)
.having (SALES.MODEL_ID.count().isGreaterThan(5))
.orderBy (BRAND.NAME.desc(), MODEL.CONFIG_NAME.asc());
/*
List<DataListEntry> list = context.getUtils().queryDataList(cmd);
for (DataListEntry dle : list)
{
System.out.println(dle.toString());
}
*/
DataListEntry entry = context.getUtils().queryDataEntry(cmd);
for (int i=0; i<entry.getFieldCount(); i++)
log.info("col {} -> {}", entry.getColumn(i).getName(), entry.getColumn(i).getBeanPropertyName());
List<QueryResult> list = context.getUtils().queryBeanList(cmd, QueryResult.class, null);
log.info("queryBeanList returnes {} items", list.size());
}
public void simpleUpdateDemo()
{
// shortcuts (for convenience)
CarSalesDB.Brand BRAND = carSales.BRAND;
CarSalesDB.Model MODEL = carSales.MODEL;
// create command
DBCommand cmd = context.createCommand()
.set (MODEL.BASE_PRICE.to(55000)) // set the price-tag
.join (MODEL.WMI, BRAND.WMI)
.where(BRAND.NAME.is("Tesla"))
.where(MODEL.NAME.is("Model 3").and(MODEL.TRIM.is("Performance")));
/*
* Clone test
DBCommand cl1 = cmd.clone();
cl1.set(MODEL.BASE_PRICE.to(66000)); // set the price-tag
cl1.where(BRAND.NAME.is("Foo"));
log.info("cmd= {} params={}", cmd.getUpdate(), cmd.getParamValues());
log.info("cmd= {} params={}", cl1.getUpdate(), cl1.getParamValues());
*/
// and off you go...
context.executeUpdate(cmd);
}
private void queryViewDemo()
{
/*
DBRecord rec = new DBRecord(context, carSales.DEALER_BRANDS);
rec.read(DBRecord.key(1, "5YJ"));
DealershipType dst1 = rec.getEnum(carSales.DEALER_BRANDS.DEALERSHIP_TYPE);
String dsn1 = rec.getString(carSales.DEALER_BRANDS.DEALERSHIP_TYPE);
log.info("DealershipType {}", dsn1);
*/
// shortcuts (for convenience)
DealerSalesView DSV = carSales.DEALER_SALES_VIEW;
// create command
DBCommand cmd = context.createCommand()
.select (DSV.getColumns())
.orderBy (DSV.SALE_YEAR, DSV.DEALER_COUNTRY);
List<DataListEntry> list = context.getUtils().queryDataList(cmd);
for (DataListEntry dle : list)
{
DealershipType dst = dle.getEnum(DSV.DEALERSHIP_TYPE);
Options opt = DSV.DEALERSHIP_TYPE.getOptions();
String dsn = dle.getString(DSV.DEALERSHIP_TYPE);
log.info("DealershipType {}-->{}", dsn, dle.format(DSV.DEALERSHIP_TYPE));
System.out.println(dle.toString());
}
}
/**
* <PRE>
* Opens and returns a JDBC-Connection.
* JDBC url, user and password for the connection are obtained from the SampleConfig bean
* Please use the config.xml file to change connection params.
* </PRE>
*/
private static Connection getJDBCConnection()
{
// Establish a new database connection
Connection conn = null;
try
{
// Connect to the database
String jdbcDriverClass = config.getJdbcClass();
log.info("Creating JDBC-Driver of type \"{}\"", jdbcDriverClass);
Class.forName(jdbcDriverClass).newInstance();
log.info("Connecting to Database'" + config.getJdbcURL() + "' / User=" + config.getJdbcUser());
conn = DriverManager.getConnection(config.getJdbcURL(), config.getJdbcUser(), config.getJdbcPwd());
log.info("Connected successfully");
// set the AutoCommit to false this session. You must commit
// explicitly now
conn.setAutoCommit(false);
log.info("AutoCommit is " + conn.getAutoCommit());
} catch (Exception e)
{
log.error("Failed to connect to '" + config.getJdbcURL() + "' / User=" + config.getJdbcUser());
log.error(e.toString());
throw new RuntimeException(e);
}
return conn;
}
/**
* Creates an Empire-db DatabaseDriver for the given provider and applies dbms specific configuration
*/
private static DBMSHandler getDBMSHandler(String provider)
{
try
{ // Get Driver Class Name
String dbmsHandlerClass = config.getDbmsHandlerClass();
if (StringUtils.isEmpty(dbmsHandlerClass))
throw new RuntimeException("Configuration error: Element 'dbmsHandlerClass' not found in node 'properties-"+provider+"'");
// Create dbms
DBMSHandler dbms = (DBMSHandler) Class.forName(dbmsHandlerClass).newInstance();
// Configure dbms
config.readProperties(dbms, "properties-"+provider, "dbmsHandlerProperites");
// done
return dbms;
} catch (Exception e)
{ // catch any checked exception and forward it
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* <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>
* <P>
* @param conn a connection to the database
*/
private void bulkProcessRecords()
{
// Define the query
DBCommand cmd = context.createCommand();
// Define shortcuts for tables used - not necessary but convenient
SampleAdvDB.Employees EMP = T_EMP;
// 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
DBRecord record = new DBRecord(context, EMP);
// Disable rollback handling to improve performance
record.setRollbackHandlingEnabled(false);
while (reader.moveNext())
{
// Calculate sum
int sum = 0;
for (int i=0; i<reader.getFieldCount(); i++)
sum += calcCharSum(reader.getString(i));
// Init updateable record
reader.initRecord(record);
// reader
record.set(T_EMP.C_CHECKSUM, sum);
record.update();
}
// Done
context.commit();
} finally
{
// always close Reader
reader.close();
}
}
private int calcCharSum(String value)
{
int sum = 0;
if (value!=null)
{ // calcCharSum
int len = value.length();
for (int i=0; i<len; i++)
sum += value.charAt(i);
}
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)
{
// First, add a new column to the Table object
DBTableColumn C_FOO = db.T_EMPLOYEES.addColumn("FOO", 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:");
DBSQLScript script = new DBSQLScript(context);
db.getDbms().getDDLScript(DDLActionType.CREATE, C_FOO, 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");
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);
script.clear();
db.getDbms().getDDLScript(DDLActionType.ALTER, C_FOO, 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!");
rec.update();
// Finally, drop the column again
System.out.println("Dropping the FOO column from the employee table:");
script.clear();
db.getDbms().getDDLScript(DDLActionType.DROP, C_FOO, script);
script.executeAll();
}
/**
* This function demonstrates the use of the DBQuery object.<BR>
* First a DBQuery is used to define a subquery that gets the latest employee department history record.<BR>
* This subquery is then used inside another query to list all employees with the current department.<BR>
* <P>
* In the second part, another DBQuery object is used to read a record that holds information from both
* the employee and department table. When the information is modified and the record's update method is
* called, then both tables are updated.
* <P>
* @param conn
* @param employeeId
*/
private void querySample(int employeeId)
{
// Define the sub query
DBCommand subCmd = context.createCommand();
DBColumnExpr MAX_DATE_FROM = T_EDH.C_DATE_FROM.max().as(T_EDH.C_DATE_FROM);
subCmd.select(T_EDH.C_EMPLOYEE_ID, MAX_DATE_FROM);
subCmd.groupBy(T_EDH.C_EMPLOYEE_ID);
DBQuery Q_MAX_DATE = new DBQuery(subCmd);
// Define the query
DBCommand cmd = context.createCommand();
// Select required columns
cmd.select(T_EMP.C_EMPLOYEE_ID, T_EMP.C_FULLNAME);
cmd.select(T_EMP.C_GENDER, T_EMP.C_PHONE_NUMBER);
cmd.select(T_DEP.C_DEPARTMENT_ID, T_DEP.C_NAME, T_DEP.C_BUSINESS_UNIT);
cmd.select(T_EMP.C_UPDATE_TIMESTAMP, T_DEP.C_UPDATE_TIMESTAMP);
// Set Joins
cmd.join(T_EDH.C_EMPLOYEE_ID, Q_MAX_DATE.column(T_EDH.C_EMPLOYEE_ID),
T_EDH.C_DATE_FROM.is(Q_MAX_DATE.column(MAX_DATE_FROM)));
cmd.join(T_EMP.C_EMPLOYEE_ID, T_EDH.C_EMPLOYEE_ID);
cmd.join(T_DEP.C_DEPARTMENT_ID, T_EDH.C_DEPARTMENT_ID);
// Set Constraints
cmd.where(T_EMP.C_RETIRED.is(false));
// Set Order
cmd.orderBy(T_EMP.C_LASTNAME);
cmd.orderBy(T_EMP.C_FIRSTNAME);
// Query Records and print output
printQueryResults(cmd);
// Define an updateable query
DBQuery Q_EMP_DEP = new DBQuery(cmd, T_EMP.C_EMPLOYEE_ID);
DBRecord rec = new DBRecord(context, Q_EMP_DEP);
// Modify and Update fields from both Employee and Department
rec.read(employeeId)
.set(T_EMP.C_PHONE_NUMBER, "0815-4711")
.set(T_DEP.C_BUSINESS_UNIT, "AUTO")
.update();
// Successfully updated
System.out.println("The employee has been sucessfully updated");
}
/**
* testTransactionCreate
* @param context
* @param idDep
*
private int testTransactionCreate(long idDep)
{
// Shortcut for convenience
SampleDB.Employees EMP = db.EMPLOYEES;
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));
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));
context.rollback();
rec.set(EMP.FIRSTNAME, "Dr. Foo");
rec.update();
log.info("Timestamp {}", rec.getString(EMP.UPDATE_TIMESTAMP));
rec.delete();
context.rollback();
// insert final
rec.update();
log.info("Timestamp {}", rec.getString(EMP.UPDATE_TIMESTAMP));
log.info("testTransactionCreate performed OK");
context.commit();
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));
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));
rec.delete();
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()));
rec.update();
log.info("Transaction performed OK");
}
*/
/**
* This function demonstrates cascaded deletes.
* See DBRelation.setOnDeleteAction()
*
* @param idEmployee the id of the employee to delete
* @param idDepartment the id of the department to delete
* @param conn the connection
*/
private void deleteRecordSample(int idEmployee, int idDepartment)
{
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");
// Delete a department
// This statement is designed to fail since cascaded deletes are not on!
try {
db.T_DEPARTMENTS.deleteRecord(idDepartment, context);
} catch(ConstraintViolationException e) {
System.out.println("Delete of department failed as expected 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.");
}
}
/**
* This functions prints the results of a query which is performed using the supplied command
* @param cmd the command to be used for performing the query
* @param conn the connection
*/
private void printQueryResults(DBCommand cmd)
{
// 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 column titles
System.out.println("---------------------------------");
int count = reader.getFieldCount();
for (int i=0; i<count; i++)
{ // Print all column names
DBColumnExpr c = reader.getColumn(i);
if (i>0)
System.out.print("\t");
System.out.print(c.getName());
}
// Print output
System.out.println("");
// Text-Output by iterating through all records.
while (reader.moveNext())
{
for (int i=0; i<count; i++)
{ // Print all field values
if (i>0)
System.out.print("\t");
// Check if conversion is necessary
DBColumnExpr c = reader.getColumn(i);
Options opt = c.getOptions();
if (opt!=null)
{ // Option Lookup
System.out.print(opt.get(reader.getValue(i)));
}
else
{ // Print String
System.out.print(reader.getString(i));
}
}
System.out.println("");
}
} finally
{ // always close Reader
reader.close();
}
}
}