среда, 16 сентября 2015 г.

Oracle. Как создать FK на поле из таблицы в другой схеме.

 По умолчанию, при попытке создать FK на поле из таблицы в другой схемы, получаем ошибку "недостаточно прав". Соответственно, надо добавить права приблизительно так:

GRANT REFERENCES ON <таблица из другой схемы> TO <пользователь, где таблица, в которой создаётся FK>;

Пример


-- добавляем разрешение
GRANT REFERENCES ON USER1.T15 TO USER2;

-- FK в таблице USER2.FK_TEST
alter table FK_TEST
  add constraint FK_F1 foreign key (F1)
  references USER1.T15(F1_ID);

Здесь,
таблица НА которую ссылается FK называется T15 и находится в пользователе USER1 (поле F1_ID),
а таблица, поле КОТОРОЙ ссылается на FK находится в пользователе USER2 и называется FK_TEST (поле с FK, соответственно F1)

Вот тут пример подробнее : http://www.akadia.com/services/ora_references_constraint.html

четверг, 12 марта 2015 г.

Перехват обращений к статическим ресурсам в Spring(3.2.2)


Дано

MVC-конфигурация с контроллерами и статическими ресурсами, которые не проходят через DispatcherServlet.

Требуется

"Перехватить" вызовы статических ресурсов (например, для подсчёта количества обращений к ним, времени, которое требуется на отдачу сервером и т.п.)


Конфигурация

web.xml:

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>testServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>testServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>


applicationContext.xml

    <!-- статические ресурсы (которые не должны проходить через DispatcherServlet) -->
    <mvc:resources mapping="/static/**" location="/static/"/>
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/js/*"/>
            <bean class="ru.pevgen.test.RequestProcessingTimeInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>

RequestProcessingTimeInterceptor.java

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
public class RequestProcessingTimeInterceptor extends HandlerInterceptorAdapter {
    private static final Logger logger = LoggerFactory.getLogger(RequestProcessingTimeInterceptor.class);
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        long startTime = System.currentTimeMillis();
        logger.info("Request URL::" + request.getRequestURL().toString()
                + ":: Start Time=" + System.currentTimeMillis());
        request.setAttribute("startTime", startTime);
        //if returned false, we need to make sure 'response' is sent
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("Request URL::" + request.getRequestURL().toString()
                + " Sent to Handler :: Current Time=" + System.currentTimeMillis());
        //we can add attributes in the modelAndView and use that in the view page
    }
    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        long startTime = (Long) request.getAttribute("startTime");
        logger.info("Request URL::" + request.getRequestURL().toString()
                + ":: End Time=" + System.currentTimeMillis());
        logger.info("Request URL::" + request.getRequestURL().toString()
                + ":: Time Taken=" + (System.currentTimeMillis() - startTime));
    }
}

Пример честно содран отсюда: http://www.journaldev.com/2676/spring-mvc-interceptors-example-handlerinterceptor-and-handlerinterceptoradapter
Я использовал spring 3.2.2, на остальных не проверял

четверг, 9 октября 2014 г.

ARCHIVELOG - посмотреть/включить/выключить

Посмотреть состояние

-- режим архивлогов
SQL> SELECT LOG_MODE FROM SYS.V$DATABASE;

-- пути и количество архивлогов
SQL> ARCHIVE log list;

Изменить размещение

SQL> ALTER SYSTEM SET log_archive_dest_1='location=/u01/oradata/MYSID/archive/' SCOPE=spfile;
SQL> ALTER SYSTEM SET log_archive_format='%t_%s_%r.arc' SCOPE=spfile;


Включить режим (перевод в ARСHIVELOG)

SQL> shutdown immediate
SQL> startup mount;
SQL> alter database archivelog;
SQL> alter database open;

Выключить режим (перевод в NOARСHIVELOG)

SQL> shutdown immediate
SQL> startup mount;
SQL> alter database noarchivelog;
SQL> alter database open;

Заметки новичка о pfile/spfile

pfile (parameter file)
- текстовый файл с параметрами запуска БД (обычное название init$ORACLE_SID.ora)

spfile (server parameter file)
- двоичный файл с параметрами, начиная с какой-то версии Oracle (обычное название spfile$ORACLE_SID.ora);
- руками менять нельзя

Размещаются в:
$ORACLE_HOME/dbs (linux)
$ORACLE_HOME\database (Win)

Главное, на мой взгляд, отличие: 
 при использовании spfile комманда ALTER SYSTEM SET .. вносит изменения в настройки, без рестарта БД

Порядок поиска файла параметров при старте БД:
Oracle будет использовать файл параметров в следующем порядке (т.е. какой первый найдёт, тот и загрузит):
spfile$ORACLE_SID.ora
spfile.ora
init$ORACLE_SID.ora

Создание pfile/spfile:
-- создать pfile из текущих настроек БД (то, что сейчас запущено)
CREATE PFILE = '/tmp/orabkp/my_init2.ora' FROM MEMORY;

-- создать pfile/spfile из текущего spfile
CREATE PFILE = '/tmp/orabkp/my_init.ora' FROM SPFILE;

-- создать spfile из pfile
CREATE SPFILE = '/tmp/orabkp/sparams2.ora' FROM PFILE='/tmp/orabkp/my_init2.ora';

Старт БД из явного pfile:
shutdown immediate
STARTUP PFILE='/tmp/orabkp/my_init2.ora' MOUNT;
alter database open;

Стартовать с явным spfile нельзя, но можно сделать следующее:
1. startup c явным pfile
2. create spfile from pfile;
3. shutdown immediate;
4. startup (if you don't say pfile= then the database will start with the spfile)

Вообще, про startup здесь:startup(удобно читать) и в доках: strtup (Oradoc 11g)

Примечание ( из форумов sql.ru)
1. экземпляр при старте использует файлы параметров, находящиеся в ORACLE_HOME\database (если явно не указать STARTUP PFILE=...)
2. если там есть и pfile, и spfile - используется spfile
3. если используется spfile, то команда ALTER SYSTEM SET... может вносить изменения и в память (для воздействия немедлено), и в spfile. При использовании pfile ALTER SYSTEM SET... влияет только на текущий экземпляр, а изменения в pfile надо не забыть внести ручками
4. spfile ручками менять нельзя
5. в Oracle >=10 при использовании spfile и ASMM (автоматического управления памятью) экземпляр сам записывает в spfile текущие значения размеров областей памяти

понедельник, 1 сентября 2014 г.

Доступ к Appender-ам logback в коде

Мы почти везде используем для логирования logback. Иногда надо получить доступ к его Appender-ам в runtime. Зачем ? Например, если я хочу получить пути файлов, в которые идёт запись логов - чтобы архивировать и передать по http клиенту (если это, скажем, web-приложение).

Пример доступа :

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
// проходим по всем loggers
for (ch.qos.logback.classic.Logger logger : lc.getLoggerList()) {
    // от каждого logger получаем его appenders
    Iterator iter = logger.iteratorForAppenders();
    while (iter.hasNext()) {
        Appender appender = (Appender) iter.next();
        // тут приходится анализировать конкретные классы 
        if (appender instanceof FileAppender) {
                  ....
        }
    }
}

пятница, 29 августа 2014 г.

Два контекста Spring MVC. Порядок загрузки.

По мотивам прочтения вот этого поста http://sgdev-blog.blogspot.sg/2014/07/spring-mvc-common-mistakes.html

В web приложениях со springframework, я чётко разделяю srping-овыйе контексты -
  - mvc.xml:  настройки, относящиеся к view, а точнее к "внешнему" web-взаимодействию (сюда входят намапленные web-контроллеры, ресурсы и т.п.)
  - services.xml: настройки, которые содержат непосредственно компоненты логики, в том числе, связки с БД, репозитории, и т.п.

Собственно, сделано это, чтобы не грузились компоненты по два раза, в двух контекстах. А в статье указанной выше  описано почему это происходит и разумные рекомендации. Которым я оказывается уже следую.


Чего я не знал, и что иногда имеет важное значение - это последовательность загрузки контекстов.

1. Сначала грузится тот контекст, что описан в ContextLoadListener(в моём случае services.xml)
2. Потом, при инициализации сервлета, грузится контекст, описанный в DispatcherServlet (mvc.xml в параметре contextConfigLocation или, по умолчанию, ${servlet.name}-context.xml)

среда, 6 августа 2014 г.

Получение объёма БД Oracle (в Гб)

Файлы БД описаны в   v$datafile 

Сам sql-запрос общего объёма :

select round(sum(bytes)/1024/1024/1024,2) || ' Gb' from v$datafile