Вставка / обновление строк в таблицу БД, где строки получаются из VO [Backed by EO] на основе Union Query
Jdev Версия: 11.1.1.7
Я создал отдел EO на основе отдела VO со следующим запросом:
SELECT DeptEO.DEPARTMENT_ID,
DeptEO.DEPARTMENT_NAME,
DeptEO.MANAGER_ID,
DeptEO.LOCATION_ID,
DeptEO.ACTIVE
FROM DEPARTMENTS DeptEO where DeptEO.DEPARTMENT_ID > 250
UNION
SELECT 280 , 'Advertising',200,1700,'Y' from Dual
Для простоты я использовал пример оператора из двойной таблицы, в реальном сценарии запрос после предложения UNION будет заполняться из таблицы. После выполнения запроса я получаю желаемый результат в пользовательском интерфейсе.
Теперь мое требование состоит в том, чтобы вставить эту вновь созданную строку с DEPARTMENT_ID, равным 280, в таблицу DB DEPARTMENTS. При фиксации ADF выдает ошибку как " oracle.jbo.RowAlreadyDeletedException: JBO-29114 ", которая является правильной, так как эта строка отсутствует в таблице БД, поэтому, когда она идет для получения блокировки строки для обновления, она не находит что-нибудь.
Есть ли способ, которым я могу поручить ADF рассмотреть эту строку для вставки, а не обновления. Мы также попытались заполнить данные этой строки новым экземпляром строки, созданным из RowSetIterator, а затем удалить строку виновника, вызвав removeFromCollection(), а затем вставив дублированную строку, но все же не повезло.
Другие подходы, о которых мы думаем:
1- Создайте другой VO/EO и вставьте значения в таблицу через них. 2. Создайте представление БД для этого запроса и активируйте его в этом представлении, поэтому, когда происходит операция обновления, мы выполняем нашу логику в триггере, т.е. решаем, обновлять или вставлять данные.
Подскажите, пожалуйста, что нужно сделать в таком сценарии.
С Уважением,
Сиддхарт
Изменить: код для вставки строки (то, что я пытался, но это не работает)
RowSetIterator rsi=iterator.getRowSetIterator();
Row editableRow= rsi.createRow();
while(rsi.hasNext()){
Row r =rsi.next();
if((""+r.getAttribute("DepartmentId")).toString().equals("280") ){
System.err.println("? Equality row found!!!");
editableRow.setAttribute("DepartmentId", r.getAttribute("DepartmentId"));
editableRow.setAttribute("DepartmentName", r.getAttribute("DepartmentName"));
editableRow.setAttribute("ManagerId", r.getAttribute("ManagerId"));
editableRow.setAttribute("LocationId", r.getAttribute("LocationId"));
editableRow.setAttribute("Active", r.getAttribute("Active"));
rsi.removeCurrentRowFromCollection();
}
}
if(editableRow !=null){
System.err.println("? Row value after removal : "+editableRow.getAttribute("DepartmentName"));
rsi.insertRow(editableRow);
operBindingCommit.execute();
}
2 ответа
Ваш вариант использования может быть реализован несколькими способами. Первый способ - выполнить итерацию по набору строк в управляемом компоненте и проверить, существует ли отдел с идентификатором 280, если да, то обновить строку, в противном случае вызвать Create с параметрами для VO отдела. Второй способ, и он сказал бы, что лучше, - это создать метод для обновления / вставки на уровне бизнес-компонента, либо в ViewObjectImpl, либо в ApplicationModuleImpl, а затем вызвать его из управляемого компонента.
Вот пример кода для метода вставки / обновления, написанный на VOImpl
public void updateInsertJobs(String jobId, String jobTitle,
String minSalary, String maxSalary)
{
RowSetIterator rSet = this.createRowSetIterator(null);
JobsViewRowImpl row = new JobsViewRowImpl();
Boolean jobExist = false;
if (null != jobId)
{
try
{
while (rSet.hasNext())
{
row = (JobsViewRowImpl) rSet.next();
if (row.getJobId().equals(jobId))
{
row.setJobTitle(jobTitle);
row.setMinSalary(new Number(minSalary));
row.setMaxSalary(new Number(maxSalary));
jobExist = true;
}
}
if (!jobExist)
{
JobsViewRowImpl r = (JobsViewRowImpl) this.createRow();
r.setJobId(jobId);
r.setJobTitle(jobTitle);
r.setMinSalary(new Number(minSalary));
r.setMaxSalary(new Number(maxSalary));
this.insertRow(r);
}
this.getDBTransaction().commit();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Убедитесь, что метод открыт в клиентском интерфейсе, чтобы иметь доступ к нему из управления данными.
Вот как вызвать метод из управляемого компонента:
public void insertUpdateData(ActionEvent actionEvent)
{
BindingContainer bc =
BindingContext.getCurrent().getCurrentBindingsEntry();
OperationBinding oB = bc.getOperationBinding("updateInsertJobs");
oB.getParamsMap().put("jobId", "TI_STF");
oB.getParamsMap().put("jobTitle", "Technical Staff");
oB.getParamsMap().put("minSalary", "5000");
oB.getParamsMap().put("maxSalary", "18000");
oB.execute();
}
Некоторые ссылки, которые могут быть полезны:
Ваш объект просмотра становится доступным только для чтения из-за пользовательского запроса SQL.
Однако вы все еще можете создать строку в таблице dept с помощью объекта.
Создать реализацию Java, включая средства доступа для DeptEO
,
Создайте пользовательский метод в объекте просмотра и создайте новый объект или обновите существующий, используя определение объекта. Чтобы найти, что требуемая строка существует, вы можете проверить, что сущность с этим ключом уже существует. Примерно так (при условии, что deptId - ваш первичный ключ):
public void createOrUpdateDept(BigInteger deptId){
DeptEOImpl dept;
EntityDefImpl deptDef = DeptEOImpl.getDefinitionObject();
Key key = new Key(new Object[]{deptId});
dept = deptDef.findByPrimaryKey(getDBTransaction(), key);
if (dept == null){
// Creating new entity if it doesn't exist
dept = deptDef.createInstance2(getDBTransaction(), null);
dept.setDepartmentId(deptId);
}
// Changing other attributes
dept.setDepartmentName("New name");
// Commiting changes and refreshing ViewObject if required
getDBTransaction().commit();
executeQuery();
}
Этот код является просто примером, используйте его как ссылку / идею, не копируйте и не вставляйте слепо.