2015年9月14日 星期一

custom annotation for method

先說,為了做 junit,是要做給別人看的~
所以文件要求的項目,格式都得要有~

但是......
因為工程師都很討厭寫文件...
因為工程師也很懶得寫註解...
因為懶得寫那些制式log...

所以就寫了一個 annotation ,來處裡~

很一般的annotation的作法~

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface JUnitTestAnnotation {
   
    String testName() default "";
    String testInput() default "";
    String testResult() default "";
    String testMemo() default "";
}

呼叫annotation的method
@JUnitTestAnnotation (
        testName="查詢-無條件查詢",
        testInput="無輸入",
        testMemo="查詢資料",
        testResult="數筆資料"
    )
    public void testQueryList1() {
        this.logStart();

然後~就可以開始掉 java.lang.reflact 的書包了~
在一開始 load 的時後,把全部的method annotation load進來
        Method[] ms = this.getClass().getMethods();
        for(int i = 0 ; i < ms.length ; i++)  {
            Method m = ms[i];
            if(m.isAnnotationPresent(JUnitTestAnnotation.class))  {
                JUnitTestAnnotation ano = m.getAnnotation(JUnitTestAnnotation.class);
                mpAno.put(m.getName(), ano);
            }
        }

然後在呼叫 logStart() 裡面,先取到「現在call 的method name」
StackTraceElement 是個很有趣的東西,把他的內容印出來。會有種熟析的fu...
原則上,第1個會是 「現在的method」,第2個就會是「前面 call 這個method 」的method...
(這真是個很妙的寫法~宅力又上升了XD)
        //StackTraceElement[] se = Thread.currentThread().getStackTrace();
        //for(int i = 0 ; i < se.length ; i++)  {
        //    System.out.println("????   ["+i+"]="+se[i].getMethodName());
        //}
        String m = null;
        try  {
            m = Thread.currentThread().getStackTrace()[2].getMethodName();
        }  catch(Exception e)  {
            return;
        }

然後拿到現在呼叫 logStart 的 method,就可以拿到他的 annotation...
        if(mpAno.containsKey(m))  {
            JUnitTestAnnotation an = (JUnitTestAnnotation)mpAno.get(m);
            logger.info("===Junit method: " + cName +"."+m);
            logger.info("===測試名稱: " + an.testName());
            logger.info("===輸入參數: " + an.testInput());
            logger.info("===預期結果: " + an.testResult());
            if(an.testMemo() != null && an.testMemo().length() > 0)  {
                logger.info("===備註: " + an.testMemo());
            }
        }

\(^_^)/然後就可以很方便的產生一堆制式的log了~

2015年9月11日 星期五

oracle 備忘

出來混總是會碰到的~其實我對甲骨文的印象很不好~又肥又胖又貴...
(快十年前,硬碟還很小,RAM 2G就很強大的時後,oracle一裝就馬上讓電腦慢到爆!)
(然後買了Java...又把人家搞爛)

不過還是又看到他了一.一|||...
是說用的方法網路資源很多,就當個記錄就是~

好吧Orz...先說一下工具的部份。
工具大家似乎都是使用 PL/SQL Developer。不過他要吃 oracle 的 ora 檔,還得要先裝一個oracle client(還好有人有現成的copy來用就沒差)...
目前 oracle 官網放的是叫 SQL Developer,老實說,難用到不知道要怎麼用,然後他連接的方式並不會產生ora檔~所以...就直接放棄他了一.一...
另外我平常使用的是小松鼠squirrel-sql,是一個用純 jdbc 實作出來的opensource...當然是很陽春,不過輕量簡單~若只是做查詢的簡單工作,又不想裝太多是個選擇。不過他抓不到 schema內的 REMARK(註解),在看會很不方便。

最後~我是用 PLSQL Developer 啦,因為要做點管理的工作Orz...
另外他對 function 等的編輯畫面好很多~

建立table~可以透過介面新增。工具好的話都不會有啥問題~
(工具 用介面建,之後匯出SQL給上線的server用就好)
就是建好要 grant 給其他 user 使用。
grant select, insert, update, delete on XXX_table to ZZZ_user;

因為有用到 synonym 的部份,要把有 owner(schema) 的轉成 public 也可以讀到~
create or replace public synonym XXX_table  for YY_owner.XXX_table;

另有做Trigger Log table的方式是~
先建一個 要 trigger 的 table,一般是 XXX_table_LOG,做好跟開 table 一樣的事。
寫 trigger,可以參照
https://docs.oracle.com/cd/E17952_01/refman-5.1-en/create-tablespace.html
因為有前人的照抄,搞懂語法後是還蠻容易的就是~
唯一要注意的就是,因為我這邊用的統一都是在 BEFORE 之前Trigger,在 insert 時要寫入LOG時,因為有些欄位是有帶預設值的,所以要記得用NVL判斷一下,已免應該有值,但寫了null~

CREATE OR REPLACE TRIGGER TG_XXX_table_LOG
  BEFORE INSERT OR DELETE OR UPDATE
  on YY_owner.XXX_table
  REFERENCING NEW AS NEW OLD AS OLD
  for each row
declare
  -- local variables here
begin
  IF updating THEN
    INSERT INTO YY_owner.XXX_table_LOG
      (Col_A,
       Col_B,
       LOG_DATE,
       LOG_ACTION)
    VALUES
      (:NEW.Col_A,
       :NEW.Col_B,
       SYSDATE,
       'U');
  ELSIF inserting THEN
    INSERT INTO YY_owner.XXX_table_LOG
      (Col_A,
       Col_B,
       LOG_DATE,
       LOG_ACTION)
    VALUES
      (:NEW.Col_A,
       NVL(:NEW.Col_B,'Y'),
       SYSDATE,
       'I');
  ELSE
    INSERT INTO YY_owner.XXX_table_LOG
      (Col_A,
       Col_B,
       LOG_DATE,
       LOG_ACTION)
    VALUES
      (:OLD.Col_A,
       :OLD.Col_B,
       SYSDATE,
       'D');
  END IF;
end;

話說...Oracle他喵的居然....把空字串當 null...一整個無言了...
所以平常常用的  IFNULL(COL_A, '') != ''
在 oracle 裡要寫成  NVL(COL_A, '') is not null
Orz...

Oracle 在下sql時,對於日期的比對 (時間區間),
無法使用  XXX_DATE >= '2015-10-02 00:00:00' 這種的寫法來下~
要利用轉日期型態  to_date('2015-10-02 00:00:00', 'YYYY-MM-DD HH24:MI:SS') 來表示 ,
要注意的是他的 format 跟一般用字也不一樣~~
可參考
http://www.techonthenet.com/oracle/functions/to_date.php




2015年9月3日 星期四

email tool: Thunderbird

最近因為買了新的nb來工作用~
新nb最麻煩的總是會碰到OFFICE的問題...
以前都可以拿公司的來灌,不過~這次公司沒有給,就只好自己生辦法~
是說也不太想弄窮人版的~就試著找些方法~

word/excel,這兩個可以用nb內建的Office Starter,有點半殘,不過能開能寫就好了~
pptx的問題,可以弄個 ppt viewer 來看(如果只是要看而已的話)
不然就是裝個OpenOffice...只是會跑版~不過因為工作性質應該用不到做ppt就想說沒差~

然後就是一定會碰到的收信問題...
一般都是用Outlook...不過因為偶也不想花錢~找了一下~
就打算用 Mozilla做的 Thunderbird...(有Mozilla掛保證,感覺就安心許多)
https://www.mozilla.org/en-US/thunderbird/

用了一下,覺得他很像就是把Firefox拿來改一改成收信軟體XD...
預設版本可以收一般 POP跟IMAP的信~
如果mail server是 MS的 exchange server,就要另外再加plugin~
我裝的是這種~
話說~ exquilla 是要收錢的Q.Q~可以試用一段時間,之後一個帳號一年10鎂吧~
https://addons.mozilla.org/en-us/thunderbird/addon/exquilla-exchange-web-services/
在設定中,要輸入exchange server的 EWS url...自動掃應該是沒用的....
https://{exchange server name}/EWS/Exchange.asmx

在Outlook上,一般只要你打 server name就可以了,在 thunderbird 上得生出一個網址來才行~
然後他也會把server上的通訊錄抓下來喔~我覺得還蠻不錯用的啦~

裡面讓偶試了有點久的功能,就是寄信給多個人時....好像自己在收信者那邊打會有問題~
要在寫信的那個視窗,打開通訊錄功能,從那邊加入,這樣多人才比較正常....

總之~我覺得還可以用啦^^~