-
Сколько людей после этого захотят вернуться в опенспейсы и насколько это будет РЕАЛЬНО НЕОБХОДИМО?
-
Как рынок труда отреагирует на это?
Author: amikhaylin
Удаленная работа и как правильно ее готовить
- Начинать и заканчивать рабочий день тогда же когда и в офисе
Если рабочий день в офисе начинается в 9:00, то и работая удаленно в 9:00 надо быть в онлайне. Из этого могут быть исключения, т.к. удаленная работа предоставляет определенную гибкость в планировании своего времени, но тогда надо помнить что 8 часов в день в любом случае принадлежат вашей работе - Время отклика – 10 минут
Это означает, что если коллеги, например через мессенджер, задают вопрос, их вопрос не проваливается в пустоту и они получают от вас отклик. Это не значит, что надо бросить ту задачу которая в текущий момент выполняется, достаточно ответить “я сейчас работаю над такой-то задачей, через Х минут отвечу на ваш вопрос”. 10 минут вполне достаточно, чтобы зафиксировать свою текущую мысль и ответить. Таким образом люди видят, что вы работаете и вы на связи. Вас не должны “искать”. Если вам нужно куда-то отлучиться, просто поставьте коллег в известность, через какой период времени вы будете на связи. - Всегда надо быть готовым отчитаться о ходе работы
Тут все очень просто: у вас спрашивают, чем вы сейчас заняты, вы отвечаете, что конкретно вы делаете, например “Я по такой-то задаче делаю то-то”. Тут главное сообщать не просто задачу, а какое действие по ней вы сейчас совершаете. - Если возникают проблемы в выполнении задачи, сразу сообщать о них
Тут все очевидно. Непонятна задача? Нехватает данных? Надо сразу “бить в колокола” а не дожидаться когда вас спросят почему задача не выполнена. Это относится к работе вообще, а не только к удаленке.
Вызов хранимой PL/SQL-функции из ADF
Наконец-то разобрался как вызывать хранимые PL/SQL процедуры/функции из ADF, и для тех кто тоже хочет разобраться, но еще этого не сделал (а также для себя, чтобы не забыть), я написал это пошаговое руководство. За основу приложения взят пример из учебника “Developing Rich Web Applications With Oracle ADF” для стандартной демо-схемы БД Oracle HR.
1) В БД добавляем простую функцию (я решил подсчитать сумму зарплаты по департаменту):
create or replace function get_sum_salary_by_dept ( p_dept_id in number ) return number as v_result number; begin select sum(salary) into v_result from employees where department_id = p_dept_id; return v_result; end get_sum_salary_by_dept;
2) Создаем имплементацию Application Module:
3) В получившийся java-класс добавляем общий метод (для удобства я его сделал статическим) запуска хранимых функций:
// Some constants public static int NUMBER = Types.NUMERIC; public static int DATE = Types.DATE; public static int VARCHAR2 = Types.VARCHAR; //Делаем метод статическим и добавляем передачу в него транзакции /* В import надо добавить import java.sql.CallableStatement; import java.sql.SQLException; import java.sql.Types; import oracle.jbo.JboException; import oracle.jbo.server.DBTransaction; */ public static Object callStoredFunction(DBTransaction tr, int sqlReturnType, String stmt, Object[] bindVars) { CallableStatement st = null; try { // 1. Create a JDBC CallabledStatement st = tr.createCallableStatement( "begin ? := "+stmt+";end;",0); // 2. Register the first bind variable for the return value st.registerOutParameter(1, sqlReturnType); if (bindVars != null) { // 3. Loop over values for the bind variables passed in, if any for (int z = 0; z < bindVars.length; z++) { // 4. Set the value of user-supplied bind vars in the stmt st.setObject(z + 2, bindVars[z]); } } // 5. Set the value of user-supplied bind vars in the stmt st.executeUpdate(); // 6. Return the value of the first bind variable return st.getObject(1); } catch (SQLException e) { throw new JboException(e); } finally { if (st != null) { try { // 7. Close the statement st.close(); } catch (SQLException e) { throw new JboException(e); } } } }
4) Генерируем класс для объекта сущности:
5) В получившийся класс добавляем метод:
public Number callGetSumSalaryByDept() {
Number n = this.getDepartmentId();
return (Number)AppModuleImpl.callStoredFunction(getDBTransaction(),
AppModuleImpl.NUMBER, “get_sum_salary_by_dept(?)”, new Object[]{n});
}
6) Генерируем классы для объекта представления и строки представления:
7) В класс объекта представления (в моем примере DepartmentsViewImpl.java) добавляем метод, вызывающий метод класса сущности:
public Float getDepartmentSalarySum(Row row){ DepartmentsViewRowImpl currentRow = (DepartmentsViewRowImpl)row; DepartmentsImpl departmentEntity = currentRow.getDepartments(); Float res = departmentEntity.callGetSumSalaryByDept().floatValue(); return res; }
8) В свойствах представления, на вкладке Java, в разделе Client Interface, кликаем кнопку редактирования и, в открывшемся окне, переносим наш метод в Selected:
9) С моделью на этом все. Нажимаем Save All и Rebuid All и переходим к интерфейсу
10) Для управления я взял основную страницу приложения (в моем примере DeptEmpPage.jsf). В AppModuleDataControl присутствует наш метод:
11) Из палитры компонентов бросаем на страницу кнопку (Button):
12) У отмеченной кнопки нажимаем на выпадающее меню (Button Actions, справа от кнопки) и выбираем Bind to ADF Control в котором выбираем наш метод:
После этого откроется окно Edit Action Binding:
В этом окне, в параметрах, в колонке Value, нужно открыть выпадающий список и выбрать Show El Expression Builder. В открывшемся окне выбрать источник откуда параметр получит строку (в моем примере текущая строка):
Нажимаем OK везде, где оно есть
13) В свойствах кнопки, в поле Text переименовываем ее в что-либо более человечное
14) Из Data Control кидаем возвращаемое значение метода на страницу и выбираем Text –> ADF Output Text w/ Label (можем сразу и изменить label):
15) Теперь создадим Partial trigger, чтобы после вызова функции, в компоненте Output Text отобразилось возвращаемое значение. Для этого в свойствах текста (Output Text), в разделе Behavior, нажимаем правую кнопку на свойстве Partial Triggers и выбираем Edit. В открывшемся окне переносим, созданную ранее кнопку в Selected:
Нажимаем OK
16) Сохраняем и запускаем наше приложение. После запуска нажимаем кнопку и наслаждаемся результатом:
Ссылки:
Мой готовый пример
руководство Developing Rich Web Applications With Oracle ADF
раздел документации Developing Fusion Web Applications with Oracle Application Development Framework – 16 Extending Business Components Functionality
Создание внешних ключей
Из найденого в черновиках. Данный скрипт применялся для докручивания БД, где внешнии ключи отсутствовали как класс
и связи между таблицами строились на основе наименования полей.
declare vSQL varchar2(2000); vi number; begin vi := 1; for c in ( select a.table_name, a.column_name, b.table_name pk_table from user_tab_columns a, user_constraints b, user_ind_columns c where (a.column_name like 'KD_%' or (a.column_name like 'ID_%' and a.column_name!='ID_USR')) and not exists (select 1 from user_constraints b1, user_ind_columns c1 where b1.table_name=a.table_name and b1.constraint_type='P' and c1.index_name=b1.index_name and c1.column_name=a.column_name) and b.constraint_type='P' and b.table_name!=a.table_name and b.index_name=c.index_name and c.column_name = a.column_name) loop begin vSQL:='create index '||c.table_name||'_i'||to_char(vi)||' on '||c.table_name||' ('||c.column_name||')'; execute immediate vSQL; vi:=vi+1; exception when others then null; end; begin vSQL:='alter table '||c.table_name||' add constraint '||c.table_name||'_fk'||to_char(vi)||' foreign key ('||c.column_name||') '|| 'references '||c.pk_table||' ('||c.column_name||')'; execute immediate vSQL; vi:=vi+1; exception when others then dbms_output.put_line(c.table_name||c.column_name); dbms_output.put_line(vSQL); end; end loop; end;
Типовая задача с собеседований
На которой я почему-то залипаю (при том что знаю решение):
Есть таблица:
create table t
(id number,
field_name varchar2(20),
string_value varchar2(20),
number_value number);
insert into t (id, field_name, string_value, number_value)
values (1, ‘Name’, ‘John’, null);
insert into t (id, field_name, string_value, number_value)
values (1, ‘Surname’, ‘Smith’, null);
insert into t (id, field_name, string_value, number_value)
values (1, ‘Salary’, null, 100);
insert into t (id, field_name, string_value, number_value)
values (2, ‘Name’, ‘Bill’, null);
insert into t (id, field_name, string_value, number_value)
values (2, ‘Surname’, ‘Dow’, null);
insert into t (id, field_name, string_value, number_value)
values (2, ‘Salary’, null, 200);
commit;
надо ее “развернуть” на 90 градусов.
решение простое:
select t.id,
max(decode(field_name, ‘Name’, string_value)) Name,
max(decode(field_name, ‘Surname’, string_value)) Surname,
max(decode(field_name, ‘Salary’, number_value)) Salary
from t
group by t.id;
Отладка приложения из OC4J в IDEA
Если у вас приложения для OC4J сделано в JDeveloper 10g то проблем нет – JDeveloper сам понимает контейнер и можно отлаживаться. Но что делать, если вам достается проект, собиреемый Maven’ом и содержащий в себе весь “зоопарк” Java-технологий (Spring, Hibernate и т.д.). Конфигурация для OC4J в IDEA по-умолчанию отсутствует. Поиск статей по этой проблеме на русском языке результатов не дал. Поэтому напишу свою. Все действия происходят под Windows.
Шаг 1. Настраиваем локальный OC4J контейнер
В файл oc4j.cmd вставляем:
set OC4J_JVM_ARGS=-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n -Xms512m -Xmx700m -XX:MaxPermSize=500m set JVMARGS=%OC4J_JVM_ARGS%
где address=8000 – адрес порта для отладки (это не тот порт к которому идет подключение клиентом или браузером), а -Xms512m -Xmx700m -XX:MaxPermSize=500m – настройки памяти JVM (что они обозначают не имею ни малейшего представления, потому что не настоящий java-программер)
Запускаем: oc4j –start
По-умолчанию порт выставлен как 8888, заходим в Server Control: http;//localhost:8888/em и деплоим предварительно собраный ear-файл.
Шаг 2. Настраиваем IDEA
Открываем проект (если проект сделан в Maven и не создан проект для IDEA, то сначала запускаем mvn idea:idea, а потом открываем получившийся проект)
В IDEA выбираем Run –> Edit configuration. В открывшимся окне нажимаем кнопку “Add new configuration”, в списке выбираем Remote, обзываем по человечески и меняем номер порта на тот который задан в шаге 1 у контейнера (8000)
Сохраняем.
Шаг 3. Собственно отладка
Расставляем брек-пойнты, жмем Run –> Debug ‘OC4J’. Подключаемся к контейнеру клиентом, выполняем операции, которые остановятся на брек-пойнте и будет предоставлена отладочная информация.
Вот в общем-то и все.
Отключение триггеров и констрейнтов
Делал это для подгрузки данных в Oracle из дампов. Может кому пригодится.
Сначала создаем 2 таблицы:
create table tmp_dbobj (name varchar2(50), otype varchar2(50)); create table tmp_cons_log (cname varchar2(50), ctype varchar2(1), tname varchar2(50), err_text varchar2(2000), cols varchar2(1000), vals varchar2(1000));
Отключаем:
--Выключение констрейнтов declare vDDL varchar2(2000); begin --triggers for c_trg in (select * from user_triggers where status = 'ENABLED') loop vDDL := 'alter trigger '||c_trg.trigger_name||' disable'; execute immediate vDDL; insert into tmp_dbobj (name, otype) values (c_trg.trigger_name, 'trigger'); commit; end loop; --FK for c_cons in (select * from user_constraints where constraint_type in ('R') and status = 'ENABLED' --and constraint_name not like 'SYS%' ) loop vDDL := 'alter table '||c_cons.table_name||' disable constraint '||c_cons.constraint_name; execute immediate vDDL; insert into tmp_dbobj (name, otype) values (c_cons.constraint_name, 'constraint'); commit; end loop; --UK for c_cons in (select * from user_constraints where constraint_type in ('U') and status = 'ENABLED' ) loop vDDL := 'alter table '||c_cons.table_name||' disable constraint '||c_cons.constraint_name; execute immediate vDDL; insert into tmp_dbobj (name, otype) values (c_cons.constraint_name, 'constraint'); commit; end loop; end;
Данные об отключенных объектах сохраняются в таблицу tmp_dbobj.
Включаем, при этом, если констрейнт не включается происходит проверка, результаты которой (записи на которых констрейнт падает) сохраняются в tmp_cons_log (ВНИМАНИЕ! Тут используется функция – строковый агрегатор, отсутствующая в Oracle):
--проверка и включение констрейнтов declare vSQL varchar2(1000); vDDL varchar2(2000); vCount number; begin --Уникальные констрайнты for c1 in (select a.* from tmp_dbobj a, user_constraints b where a.otype = 'constraint' and b.constraint_name = a.name and b.constraint_type = 'U') loop for c_cols in (select constraint_name, table_name, str_agg(column_name) cols, str_agg(column_name||' is null') null_cols from user_cons_columns where constraint_name = c1.name group by constraint_name, table_name) loop c_cols.null_cols := replace(c_cols.null_cols,',',' and '); vSQL := 'select 1 from dual where not exists (select '||c_cols.cols||', count(*) cnt from '|| c_cols.table_name|| ' where not ('||c_cols.null_cols||') group by '||c_cols.cols||' having count(*)>1 )'; begin execute immediate vSQL into vCount; vDDL := 'alter table '||c_cols.table_name||' enable constraint '||c1.name; execute immediate vDDL; delete from tmp_dbobj where name = c1.name; commit; exception when no_data_found then vSQL := 'begin '|| 'for c1 in ( select '||replace(c_cols.cols,',','||'',''||')||' vals from ('|| 'select '||c_cols.cols||', count(*) cnt from '||c_cols.table_name|| 'where not ('||c_cols.null_cols||') group by '||c_cols.cols||' having count(*)>1 )) loop'|| 'insert into tmp_cons_log (cname, ctype, tname, err_text, cols, vals)'|| 'values ('''||c_cols.constraint_name||''', ''U'', '''||c_cols.table_name||''', ''Дублирующие значения'', '''|| c_cols.cols||''', c1.vals); '|| 'end loop; commit; end;'; execute immediate vSQL; end; end loop; end loop; --Все остальные (FK) for c1 in (select a.*, b.table_name from tmp_dbobj a, user_constraints b where a.otype = 'constraint' and b.constraint_name = a.name and b.constraint_type = 'R') loop begin vDDL := 'alter table '||c1.table_name||' enable constraint '||c1.name; execute immediate vDDL; delete from tmp_dbobj where name = c1.name; commit; exception when others then for c_cols in (select col.constraint_name, col.table_name, r_col.table_name r_table_name, fdc_str_agg(col.column_name) cols, fdc_str_agg('r.'||r_col.column_name||' = a.'||col.column_name) w_cols, fdc_str_agg('a.'||col.column_name||' is not null') w_cols2 from user_constraints con, user_cons_columns col, user_cons_columns r_col where con.constraint_name = c1.name and col.constraint_name = con.constraint_name and r_col.constraint_name = con.r_constraint_name and col.position = r_col.position group by col.constraint_name, col.table_name, r_col.table_name) loop vSQL := 'begin '|| 'for c2 in ( select '||replace(c_cols.cols,',','||'',''||')||' vals from '|| c_cols.table_name||' a '|| 'where not exists (select 1 from '||c_cols.r_table_name||' r '|| 'where '||replace(c_cols.w_cols,',',' and ')||')'|| 'and '||replace(c_cols.w_cols2,',',' and ')|| ') loop '|| 'insert into tmp_cons_log (cname, ctype, tname, err_text, cols, vals)'|| 'values ('''||c_cols.constraint_name||''', ''R'', '''||c_cols.table_name||''', ''Нет родительской записи'', '''|| c_cols.cols||''', c2.vals); '|| 'end loop; commit; end;'; dbms_output.put_line(vSQL); execute immediate vSQL; end loop; end; end loop; --триггера for c1 in (select * from tmp_dbobj where otype = 'trigger') loop vDDL := 'alter trigger '||c1.name||' enable'; execute immediate vDDL; delete from tmp_dbobj where name = c1.name; commit; end loop; end;
Динамический SQL в Oracle. Пример
В рамках программы восстановления утраченных знаний, написал пример использования dbms_sql:
DECLARE
cSQL NUMBER; –Идентификатор курсора
vSubjOld NUMBER := 000000; –Старый ID
vSubjNew NUMBER := 111111; –Новый ID
vSQL VARCHAR2(1000);
vID NUMBER;
vUpdateSQL VARCHAR2(1000);
vRet NUMBER;
BEGIN
–Курсор по таблицам с полями которые нужно обработать
FOR c_tab IN (SELECT DISTINCT tb.TABLE_NAME, cl.COLUMN_NAME
FROM user_tab_columns cl,
user_tables tb
WHERE cl.column_name IN (‘SUBJECT_ID’,’SUBJ_ID’,’DECLARANT_ID’,’PAYER_ID’,’CARRIER_ID’,’BROKER_ID’)
AND tb.TABLE_NAME=cl.TABLE_NAME
AND tb.TABLE_NAME NOT LIKE ‘EXP_%’
AND tb.TABLE_NAME NOT LIKE ‘LEG_%’
AND tb.table_name NOT LIKE ‘TMP_%’) LOOP
dbms_output.put_line(c_tab.table_name||’.’||c_tab.column_name);
vUpdateSQL := ‘update ‘||c_tab.table_name||’ ‘||
‘set ‘||c_tab.column_name||’ = :1 ‘||
‘where ‘||c_tab.column_name||’ = :2 ‘;
–открыть курсор
cSQL:=dbms_sql.open_cursor;
BEGIN
vSQL:=’select id ‘||
‘from ‘||c_tab.table_name||’ ‘||
‘where ‘||c_tab.column_name||’ = :subj_id’;
dbms_sql.parse(cSQL, vSQL, dbms_sql.native);
–биндим переменные
dbms_sql.bind_variable(cSQL, ‘subj_id’, vSubjOld);
–Определяем колонки
dbms_sql.define_column(cSQL,1,vID);
–запускаем
vRet := dbms_sql.execute(cSQL);
LOOP
–В Oracle 11g есть чудесная функция dbms_sql.to_refcursor позволяющая сделать все проще без всех этих условий
IF dbms_sql.fetch_rows(cSQL)>0 THEN
dbms_sql.column_value(cSQL,1,vID);
dbms_output.put_line(‘ID: ‘||vID);
–Меняем
EXECUTE IMMEDIATE vUpdateSQL USING vSubjNew, vSubjOld;
ELSE
EXIT;
END IF;
END LOOP;
dbms_sql.close_cursor(cSQL);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(SQLERRM);
dbms_sql.close_cursor(cSQL);
END;
END LOOP;
–…
END;
Установка русской MSDN Library на английскую VS2010, продолжение
К сожелению выяснилось, что после установки библиотеки, описанной в предыдущей статье, не работает обновление через интернет, а так же добавление новых (например, доку по Silverlight’у) и удаление (!) старых разделов. Обидно, но студию пришлось удалить полностью, потом руками удалить HelpLibrary и потом студию поставить обратно и накатить SP1. LanguagePack на Help не трогал, видимо он остался жить в системе какой-то своей жизнью. Дальше процесс такой:
1. Правим ярлык “Manage Help Settings” как написано в предыдущей статье
2. Устанавливаем русские библиотеки из интернета
3. Правим queryManifest.?.xml: копи-пастим весь каталог с русскими библиотеками и в одной копии меняем атрибут productLocale на “EN-US”
4. Запускаем студию, проверяем. Все работает.
Установка русской MSDN Library на английскую Visual Studio 2010
Вот лично у меня локализованные среды разработки вызывают резкую антипатию (ставил ради интереса русскую Visual Studio 2008 долго искал где там Debug ), чего нельзя сказать о документации (хотя она тоже бывает переведена так, что лучше бы и не переводили). Если с 2008 студией все было просто – ставим английскую студию без MSDN потом ставим MSDN от русской студии, то с 2010 студией не все так просто, но не невозможно.
Для установки понадобится: установленная Visual Studio 2010 ENG без библиотек Help’а, дистрибутив Visual Studio 2010 RUS (можно скачать trial, устанавливать ее мы все равно не собираемся), notepad
1. Распаковываем iso с русской VS2010, вытаскиваем оттуда папки Help и ProductDocumentation
2. Из папки Help устанавливаем Language Pack (HelpSetupLP_x64_RUS.exe или HelpSetupLP_x86_RUS.exe в зависимости от системы)
3. В папке ProductDocumentation правим файл HelpContentSetup.msha заменяя значения ru-ru на en-us
4. Правим ярлык “Microsoft Visual Studio 2010\Visual Studio Tools\Manage Help Settings – ENU” в поле “Объект” меняем параметр /locale с en-US на ru-RU
5. Запускаем Manage Help Settings (должно запуститься на русском языке) и выбираем “Установить содержимое с диска”
6. В качестве “Расположения носителя справки” выбираем правленный HelpContentSetup.msha
7. Выбираем что хотим установить и давим “Обновить”
8. Залезаем в папку с установленным хелпом (по-умолчанию c:\ProgramData\Microsoft\HelpLibrary) и бекапим её
9. Заходим в catalogs\VS\100 там 2 папки: EN-US и RU-RU, переносим все из EN-US в RU-RU
10. Заходим в manifest и правим файл queryManifest.3.xml методом удаления строк как показано на картинке ниже
11. Запускаем студию, вызываем Help
12. Убеждаемся что все работает, убиваем бэкапы
PS: Вполне может быть, что какой-то шаг я пропустил, потому, что папка с заготовленной ProductDocumentation у меня была подготовленна задолго до написания этой статьи.
PS2: Вполне возможно, что шаг 9 является лишним
UPD: Продолжение