Total Pageviews

2016/02/04

[Microsoft SQL Server] How to subtract a year in SQL

Problem
I have a select SQL statement as bellows:
SELECT sta_date
FROM dbm031fa
WHERE year(sta_date) = year(CURRENT_TIMESTAMP)-2
If I would like to get the value of sta_date is the value in database subtract one year, how to do it?


How To
Microsoft SQL Server had a build-in function, DATEADD, to fulfill this requirements.
The SQL statement can be modified as following:
SELECT sta_date,
       DATEADD(YEAR, -1, sta_date)
FROM dbm031fa
WHERE year(sta_date) = year(CURRENT_TIMESTAMP)-2


Reference
[1] https://msdn.microsoft.com/zh-tw/library/ms186819(v=sql.120).aspx

2016/02/03

[Apache Commons BeanUtils] How to exclude an Object from a Collection

Problem
Assume I have a dropdown list which name 基金法人類別. 
Our customer requested to remove the first option, i.e. 普通基金, from the dropdownlist


Original code snippet:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
    @RequestMapping(value = "/getAgeTypeList", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public List<Dbm002fbVo> getAgeTypeList(
            @RequestBody(required = true) final Dbm038eFormBean formBean, Alerter alerter) {
        List<Dbm002fbVo> result = new ArrayList<Dbm002fbVo>();

        List<Dbm002fb> dbm002fbs = dbm038eService.findDropdownList("AGTPE");

        if (dbm002fbs != null && dbm002fbs.size() > 0) {
            for (Dbm002fb dbm002fb : dbm002fbs) {

                Dbm002fbVo vo = new Dbm002fbVo();
                convertToDbm002fbVo(dbm002fb, vo);

                result.add(vo);
            }
        } else {
            throw new RuntimeException("查無 基金法人類別 下拉單 (kind_code='AGTPE'");
        }

        return result;
    }


How to
We can use Apache commons BeanUtils to remove the specific object from a Collection.
Updated code snippet:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
    @RequestMapping(value = "/getAgeTypeList", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public List<Dbm002fbVo> getAgeTypeList(
            @RequestBody(required = true) final Dbm038eFormBean formBean, Alerter alerter) {
        List<Dbm002fbVo> result = new ArrayList<Dbm002fbVo>();

        List<Dbm002fb> dbm002fbs = dbm038eService.findDropdownList("AGTPE");

        List<Dbm002fb> newDbm002fbs = excludeCodeNoIsZero(dbm002fbs);

        if (newDbm002fbs != null && newDbm002fbs.size() > 0) {
            for (Dbm002fb dbm002fb : newDbm002fbs) {

                Dbm002fbVo vo = new Dbm002fbVo();
                convertToDbm002fbVo(dbm002fb, vo);

                result.add(vo);
            }
        } else {
            throw new RuntimeException("查無 基金法人類別 下拉單 (kind_code='AGTPE'");
        }

        return result;
    }

    private List<Dbm002fb> excludeCodeNoIsZero(List<Dbm002fb> dbm002fbs) {
        /**
         * The BeanPropertyValueEqualsPredicate constructor takes two parameters which determine
         * what property will be evaluated on the target object and what its expected value should
         * be.
         */
        BeanPropertyValueEqualsPredicate codeNoPredicate = new BeanPropertyValueEqualsPredicate(
                "codeNo", BigInteger.ZERO);
        /**
         * Create a new Predicate that returns true if none of the specified predicates are true. If
         * the array of predicates is empty, then this predicate returns true.
         */
        Predicate predicate = PredicateUtils.nonePredicate(new Predicate[] { codeNoPredicate });

        /**
         * Selects all elements from input collection which match the given predicate into an output
         * collection.
         */
        @SuppressWarnings("unchecked")
        List<Dbm002fb> newDbm002fbs = (List<Dbm002fb>) CollectionUtils.select(dbm002fbs, predicate);

        return newDbm002fbs;
    }



2016/02/02

[閱讀筆記] 易讀程式之美 (Part 2)


  1. C++的創造者Bjarne Stroustrup說,在我的個人經驗裡,do / while 敘述經常是錯誤與誤解的來源,我寧願把條件式列在最前面,總而言之,我會盡量避免使用do / while 敘述
  2. 修改程式碼時要以全新的角度審視,退一步以整體的角度考慮程式碼
  3. 盡量消除loop中的巢狀結構,因為巢狀結構可讀性較差
  4. 程式碼的表示式越大,就越難理解。所以,要將巨大表示式分解為更容易消化的大小
  5. 寫法很酷的程式碼,經常會對後續使用程式的人造成困擾
  6. 對邏輯表示式使用De Morgan’s Law,有時能將boolean 表示式以更清晰的方式表達,比較簡單的記法是,把not分配到各項,再反轉and / or。如,if( !(a && !b)) 改寫成 if (!a || b),if ( !(file_exists && !is_protected)) 改寫成 if (( !file_exists || is_protected))
  7. 濫用變數會造成三個問題:變數越多越難同時記住所有變數;變數存活的範圍越大,就必須記得越久;變數越常改變,越難記得目前的數值
  8. 工程就是將大問題分解成小問題在將小問題的解答組合成原本大問題的解答在程式碼應用這個原則能讓程式更強固也更易於閱讀
  9. 抽離程式碼為獨立函數,這是程式設計師每天都在做的工作
  10. 函式庫提供的介面要夠簡潔,不要太多參數,也不要有太多的設定程序,用起來不要有額外的負擔。讓程式碼看起來更佳優雅,也更簡單與強而有力
  11. 程式碼應該組織為一次只做一件事
  12. 如果程式碼很難閱讀,試著列出執行的工作,某些工作可以輕易的抽離為函數或類別,其他部分可以成為函數內邏輯的段落。分離工作細節的形式並不重要,重要的是彼此分咧,真正困難的部份在於列出所有函數執行的小工作
  13. 愛因斯坦曾說:除非能解釋讓祖母了解,不然就不算真正了解
  14. 可讀性最高的程式碼就是完全沒有程式碼
  15. 程式設計師常會低估實作功能需要的功夫,會很理想的估計實作粗糙原形所需的時間,忽略後續維護、文件以及對程式碼增加的額外負擔
  16. 程式設計師一般會高估專案正正需要的核心功能,造成許多功能來不及完成,或祇是增加應用程式的複雜度
  17. 消除不必要的需求、簡化問題非常重要,重新思考需求,在仍然能達到目的的情況下,改為解決簡化過的問題
  18. 避免過度設計
  19. 當任何系統成長時,維持系統所需的複雜度會以更快的速度成長
  20. 盡量維持程式碼小而美
  21. 測試應該易於閱讀,以便其他人可以放心地修改或其加入其他測試。測試程式碼與非測試用程式碼一樣重要。
  22. 依據一般設計原則,應該「對使用者隱藏不重要的細節,凸顯重要的細節」
  23. 錯誤訊息應該盡量清楚地提供有幫助的資訊,有時候,「自行手工打造」印出所需的訊息,會是最好的方式
  24. 測試都時候,應該挑選能完整執行程式碼所需之最簡單的集合作為輸入值。優先使用簡單、明確但能達到測試效果的輸入值
  25. 一般來說,如果在設計程式的時候體認到,「嗯,之後這段會很難測試」,這就是個停止考慮這種設計的好理由
  26. 100行容易讀的程式,比起50行艱澀難懂的程式碼要來得好

2016/02/01

[閱讀筆記] 富爸爸,窮爸爸 (Part 1)


  1. 窮人與破產者之間的區別是,破產是暫時的,貧窮是永久的
  2. 讓錢為你工作
  3. 錢來了又去,但如果你了解錢是如何運轉的,你就有了駕馭他的力量,並開始累積財富
  4. 為錢工作很容易,但是你該學習的是如何讓錢為你工作
  5. 學會讓感情跟隨你的思想,而不要讓思想跟著你的感情
  6. 所謂的財富自由,是指你的財產能避開通貨膨脹而且不斷地增加著。當資產已經多到可以自我增值,就像種下一棵樹,你年復一年地澆灌它,終於有一天它不再需要你的照料,可以自己生長了。它的根已經夠深,你現在只管開始享受它的樹蔭了。
  7. 知識才能解決問題並創造財富,不是憑財務知識掙來的錢,很快就會消失。
  8. 從長期來看,重要的不是你掙了多少錢,而是要看你能留下多少錢,以及留住多久。
  9. 你要明白資產和負債的差別。富人獲得資產,而窮人和中產階級獲得負債,只不過他們以為那些就是資產。
  10. 資產就是能把錢放進你口袋的東西,而負債是把錢從你口袋取走的東西
  11. 錢無法掩蓋人的無知,這就是為什麼經常有些人在突然得到一大筆意外之財,如遺產、加薪或中樂透後,又很快失去的原因,有些人甚至會比他得到那些錢之前的財務狀況更糟。如果你的現金流向圖示把收入都花掉,那麼最有可能的結果是增加收入的同時,也增加支出
  12. 中產階級的主要收入是工資,而當工資增加的時候,稅收也增加了,更重要的是他們的支出傾向也隨著收入增加而同等增加。他們把房子作為主要資產反覆進行投資,而不是投資於那些能帶來收入的真正資產上。
  13. 富人買入資產;窮人只有支出;中產階級買他們以為是資產的負債。
  14. 存在財務問題的人,經常是一生為別人工作的人,許多人在他們停止工作時,就變得一無所有
  15. 不要混淆事業與職業的差別,事業是你自己的資產,是為自己致富;職業是幫他人關注他的事業,並使他致富
  16. 為了財務安全,人們需要關注自己的事業,只有把你在職業所掙來的收入,用於購買可以產生收入的資產時,你才能獲得真正的財務安全
  17. 關注你自己的事業,並繼續你每天的工作你可以買些房地產,而不是負債或買一些一旦被你帶回家就沒有價值的個人用品,如汽車、高爾夫球具等
  18. 真正的資產可以分為以下幾類
    1. 不需我到場就可以正常運作的業務
    2. 股票
    3. 債券
    4. 共同基金
    5. 產生收入的房地產
    6. 票據(借據)
    7. 專利權如音樂、手稿、專利
    8. 任何其他有價值、可產生收入或可能增殖且具有很好的流通市場的東西
  19. 做一個努力工作的雇員,確保你的工作,但要不斷構築你的資產項目
  20. 當你的現金流增加時,你可以買一些奢侈品,一個重要的區別是,富人最後才買奢侈品,而窮人和中產階級會先買下諸如大房子、珠寶、鑽石、遊艇等奢侈品,因為他們想看上去很富有,實際上他們已深陷貸款的陷阱中。
  21. 記住,先建立自己的資產,然後才用資產所產生的收入購買奢侈品
  22. 政府與企業的差別在於,政府不會因為有節餘而被認為有效率並得到獎勵,反而了避免 沒有用完預算被削減預算,政府會大量花錢和僱人,雖然此舉可能是在浪費。然而,企業則會因為有節餘而被認為有效率
  23. 如果你為錢工作,你就把控制的力量給了雇主;如果讓前衛你工作,你就能控制這種力量
  24. 僅僅依賴雇主的工資,就永遠只能是一頭乖乖待擠的乳牛
  25. 擁有公司的富人,一、掙錢,二、支出、三繳稅;為公司工作的人,一、掙錢,二、繳稅,三、支出。
  26. 在真實世界,畏懼與自我懷疑是浪費我們才能的最大因素。人們往往是依靠勇氣,而不是聰明去領先於其他人的
  27. 財務智商是由四項主要技能組成
    1. 財務知識,即閱讀、理解數字的能力
    2. 投資戰略,即錢生錢的科學
    3. 市場、供給與需求。
    4. 法律規章。要關心所關會計、公司法方面的法律與規定
  28. 如果投資機會太複雜,很難弄明白,就不要去投資。簡單的數學計算和一般常識,是做好財務所需要的一切
  29. 如果你把錢投入一筆交易後只是祈禱,那是在賭博,不是在投資。在任何情況下,成功的辦法就是運用你的技術知識、智慧來減少意外情況的發生,並降低風險。
  30. 大部分人不富有的主要原因在於他們太擔心失去。勝利者是不怕失去的,但失敗者都害怕失去。失敗是成功之母,如果避開失敗,也就避開了成功。人是從跌倒中學會走路的。



2016/01/31

2016/01 Travel

進擊的巨人展



2016/01/27

[AngularJS] How to set selected row and set highlight in ng-gird pragmatically?

Requirement
After I create a new record, the program should refresh the data grid and set selected item and highlighted the selected item.


After I update an existing record, the program should refresh the data grid and set selected item and highlighted the selected item.


Here has the code snippet regarding ng-grid:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
        $scope.itemGridCols  = [ 
            {
               field : 'accountYr',
               displayName : '年度',
               cellClass: 'text-left',
               width: '150px'
            }, 
            {
               field : 'orgType',
               displayName : 'orgType',
               cellClass: 'text-left',
               visible : false
            },
            {
                field : 'orgTypeName',
                displayName : '機關類別',
                cellClass: 'text-left',
                width: '250px'
             },
             {
                field : 'masterAge',
                displayName : 'masterAge',
                cellClass: 'text-left',
                visible : false
             },
             {
                field : 'masterAgeName',
                displayName : '主管機關名稱',
                cellClass: 'text-left',
                width: '250px'
             },
             {
                field : 'ageName',
                displayName : '機關名稱',
                cellClass: 'text-left',
                width: '250px'
              },
             {
                field : 'age',
                displayName : '機關代號',
                cellClass: 'text-left',
                width: '250px'
             }
          ];
        
        $scope.itemGrid = {
                keepLastSelected: false,
                selectedItems: $scope.selectedItem,
                multiSelect : false,
                data : 'itemData',
                columnDefs : 'itemGridCols',
                enableColumnResize: true,
                afterSelectionChange : function(rowItem){ 
                    if (rowItem.selected) {
                        $scope.model.accountYr = rowItem.entity.accountYr;
                        $scope.model.orgType   = rowItem.entity.orgType;
                        $scope.model.masterAge = rowItem.entity.masterAge;
                        $scope.model.ageNm     = rowItem.entity.ageName;
                        $scope.model.age       = rowItem.entity.age;
                    }else{
                        $scope.model = {};
                        
                        $scope.model.accountYr = getCurrentYear()-1;
                    }
                }
        };

create and update button code snippet is as following:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
        $scope.createBtn = function(){
            // 驗證表單
               if (!$scope.validate(this.dbm039eForm)) {
                   return;
               }
               
               dbmService.execute("rest/create", $scope.model)
                   .then(function(response) { 
                       $scope.itemData = response;
                       cAlerter.info('新增成功');
                   }
               );
          };
          
          $scope.saveBtn = function(){
              dbmService.execute("rest/save", $scope.model)
                  .then(function(response) { 
                      $scope.itemData = response;                    
                      cAlerter.info('修改成功');
                  }
              );
          };

How To
Utilize $scope.itemGrid.selectRow(index, true); to fulfill this requirement, and remember to move this code in $timeout:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
         $scope.setSelectedRow = function(itemData, selectedItem){
              var index = 0;
              var keepGoing = true;

              angular.forEach(itemData, function(value, key) {
                  if(keepGoing){
                      if(value.accountYr == selectedItem.accountYr && 
                         value.orgType == selectedItem.orgType  && 
                         value.age == selectedItem.age){
                           index = key;
                           keepGoing = false;
                      }
                  }
              });
              
              // remember to set select row in $timeout, or it will NOT work
              $timeout(function () {
                  $scope.itemGrid.selectRow(index, true);
              },1 );
              
          };
    
        $scope.createBtn = function(){
            // 驗證表單
               if (!$scope.validate(this.dbm039eForm)) {
                   return;
               }
               
               dbmService.execute("rest/create", $scope.model)
                   .then(function(response) { 
                       $scope.itemData = response;
                       
                       //set model to selectedItem
                       $scope.selectedItem[0] = $scope.model;
                       //set selected row
                       $scope.setSelectedRow($scope.itemData, $scope.selectedItem[0]);
                       
                       cAlerter.info('新增成功');
                   }
               );
          };
          
          $scope.saveBtn = function(){
              if($scope.selectedItem.length == 0){
                  cAlerter.fatal('請選擇要修改的資料');
                  return;
              }
              
              dbmService.execute("rest/save", $scope.model)
                  .then(function(response) { 
                      $scope.itemData = response;
                      
                      // set selected row
                      $scope.setSelectedRow($scope.itemData, $scope.selectedItem[0]);
                      
                      cAlerter.info('修改成功');
                  }
              );
          };
          
         


Reference
[1] https://github.com/angular-ui/ui-grid/issues/2267

2016/01/08

[Oracle] Nulls with Comparison Conditions

Problem
Assume the data in the table is as following:
1
2
3
4
select fyr, age, type1
from ave107fa
where paydat between '1041201' and '1041231'
order by type1 ;



We can find out the value of type1 has D and null.

If I would like to find the data which Type1 is not eqal to D:
1
2
3
4
5
select fyr, age, type1
from ave107fa
where paydat between '1041201' and '1041231'
       and type1 <> 'D'
order by type1 ;

But Oracle return nothing
:


How To
In Oracle,  null represents a lack of data, a null cannot be equal or unequal to any value or to another null. Therefore, it will return nothing.

Hence, we can modify SQL statement as bellows:
1
2
3
4
5
select fyr, age, type1
from ave107fa
where paydat between '1041201' and '1041231'
      and nvl(type1, ' ') <> 'D'
order by type1 ;


The data which Type1 is null can be retrieved now:


Reference
[1] https://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements005.htm

2016/01/07

[Spring Framework] Spring Data JPA @Query

If I have an SQL query statement which is simple, and not dynamic, we can utilize @Query to fulfill out requirement.

Example 1. Apply @Query without parameter:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public interface Dbm002fbRepository extends EntityRepository<Dbm002fb, String> {

    /**
     * 找出 kind_code = 'DEBTT' 的下拉單.
     * 
     * @return the list
     */
    @Query(value = "select * from dbm002fb where kind_code='DEBTT' and is_use='Y' order by code_no", nativeQuery = true)
    List<Dbm002fb> findDEBTT();

    /**
     * 找出 kind_code = 'DEBTI' 的下拉單.
     * 
     * @return the list
     */
    @Query(value = "select * from dbm002fb where kind_code='DEBTI' and is_use='Y' order by code_no", nativeQuery = true)
    List<Dbm002fb> findDEBTI();
}


Example 2. Apply @Query and bind named parameters:
1
2
3
4
5
6
7
public interface Fms426faRepository extends EntityRepository<Fms426fa, Fms426faId>,
        Fms426faRepositoryCustom {

    @Query(value = "select * from fms426fa where accyr=:twYear and data_type='T' order by rpt_no", nativeQuery = true)
    List<Fms426fa> findTAlcAmt(@Param("twYear") String twYear);

}


Reference
[1] http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query
[2] http://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-creating-database-queries-from-method-names/

2016/01/06

[Git] The requested URL returned error: 403

Problem
When I try to clone project from GitLab, it shows the following error message




How-To
Try to use SSH instead of HTTP, this annoying problem will be resolved.




But the root cause does not know yet.