Total Pageviews

2019/03/12

[SQL Server] IF EXISTS update else insert

Scenario
If I would like to implement a SQL statement to fulfill the following requirement, how to do it?


How-To
You can utilize if exists..else to do, here has an example:
  IF EXISTS (select * from TEST where ID = :id)
    UPDATE TEST 
    SET USER_ID = :userId, 
 USER_NAME = :userName, 
 LAST_UPDATE_TIME = getdate() 
    WHERE ID = :id
  ELSE
    INSERT INTO TEST (ID, 
                      USER_ID, 
            USER_NAME, 
        CREATE_TIME, 
        LAST_UPDATE_TIME)
               VALUES (:id, 
         :userId, 
         :userName, 
         getdate(), 
         getdate())
  ;


2019/03/11

[Java] [Design Pattern] An example for Template Method Pattern

Here has four steps to demonstrate template method pattern:

1. Create an abstract class with a template method being final.
package com.example.pattern.template;

public abstract class Game {

    abstract void initializeGame();
    abstract void playGame();
    abstract void endGame();

    /**
     * template method
     */
    public final void play() {
        initializeGame();
        playGame();
        endGame();
    }

}

2. Create concrete classes extending the above class.
package com.example.pattern.template;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class FishingStrike extends Game {

    @Override
    void initializeGame() {
        log.debug("Fishing Strike initialized!");
    }

    @Override
    void playGame() {
        log.debug("Fishing Strike started! Enjoy the game!");
    }

    @Override
    void endGame() {
        log.debug("Fishing Strike finished! See you!");
    }
}


package com.example.pattern.template;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class MiniGolfKing extends Game {

    @Override
    void initializeGame() {
        log.debug("Mini Golf King initialized!");
    }

    @Override
    void playGame() {
        log.debug("Mini Golf King started! Enjoy the game!");
    }

    @Override
    void endGame() {
        log.debug("Mini Golf King finished! See you!");
    }
}


3. Create a demo class to use the Game's template method play() to demonstrate a defined way of playing game.
package com.example.pattern.template;

import org.springframework.stereotype.Component;

@Component
public class TemplatePatternDemo {

    /**
     * play fishing strike game
     */
    public void playFishingStrike() {
        Game fishingStrike = new FishingStrike();
        fishingStrike.play();
    }

    /**
     * play mini golf king game
     */
    public void playMiniGolfKing() {
        Game miniGolfKing = new MiniGolfKing();
        miniGolfKing.play();
    }

}


4. Autowired TemplatePatternDemo to play execute methods and verify output
package com.example.test;

import com.example.pattern.template.TemplatePatternDemo;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackages = "com.example")
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }

    @Bean
    CommandLineRunner run(TemplatePatternDemo demo) {
        return args -> {
            demo.playFishingStrike();
            demo.playMiniGolfKing();
        };
    }
}


[main] c.e.pattern.template.FishingStrike       : Fishing Strike initialized!
[main] c.e.pattern.template.FishingStrike       : Fishing Strike started! Enjoy the game!
[main] c.e.pattern.template.FishingStrike       : Fishing Strike finished! See you!
[main] c.example.pattern.template.MiniGolfKing  : Mini Golf King initialized!
[main] c.example.pattern.template.MiniGolfKing  : Mini Golf King started! Enjoy the game!
[main] c.example.pattern.template.MiniGolfKing  : Mini Golf King finished! See you!




2019/03/10

[Database] [Sybase] arithmetic overflow error

Problem
When I try to sum up a integer column in Sybase, I get arithmetic overflow error, how to fix it?
SELECT SUM(columnname) 
FROM tablename

How-To
Simply cast this column to big integer can solve this problem, the updated query SQL statement is as bellows;
SELECT SUM( cast(columnname as BIGINT)) 
FROM tablename

2019/03/09

[Angular 6] Can't bind to 'ngModel' since it isn't a known property of 'input'

Problem
When I try to run my html page, it showed the following error message:
When I try to run my html page, it showed the following error message:
compiler.js:1021 Uncaught Error: Template parse errors:
Can't bind to 'ngModel' since it isn't a known property of 'input'. ("up)="changeKeyword($event.target.value)"
                (keyup.esc)="clearKeyword($event.target)" [ERROR ->][(ngModel)]="keyword">
              <input type="button" value="搜尋" id="searchbutton">


How-To
I forgot to import FormsModule in my app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { Page2Component } from './page2/page2.component';

@NgModule({
  declarations: [
    AppComponent,
    Page2Component
  ],
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
     


2019/03/08

[Spring Boot] How to configure multiple datasource in Spring boot?

Problem
I have Sybase and Microsoft SQL Server database connection in my Spring boot, how to configure two data source in my project?

Sybase repository and entity classes are located in test.repository.sybase, and test.entity.sybase

Microsoft SQL Server repository and entity classes are located in test.repository.sqlserver and test.entity.sqlserver


How-To
Configure 2 database configuration in application.yml:
spring:
  jpa:
    show-sql: true
    open-in-view: false
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
  datasource:
    url: jdbc:sybase:Tds:192.168.0.1:5000/TEST
    username: user
    password: secret
    driver-class-name: com.sybase.jdbc4.jdbc.SybDriver
    hikari:
      pool-name: pool-primary
      connection-test-query: SELECT 1

sqlserver:      
    datasource:
      url: jdbc:sqlserver://192.168.0.2:1433
      username: user
      password: secret
      driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
      hikari:
        pool-name: pool-sqlserver
        connection-test-query: SELECT 1

Sybase configuration:
package test.config;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.jdbc.JdbcProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

import com.zaxxer.hikari.HikariDataSource;

@Configuration
@Primary
@EnableJpaRepositories(transactionManagerRef = "transactionManager", basePackages = {
        "test.repository.sybase" })
public class SybaseDbConfig {

    @Value("${spring.datasource.url}")
    private String url;

    @Value("${spring.datasource.username}")
    private String username;

    @Value("${spring.datasource.password}")
    private String password;

    @Value("${spring.datasource.driver-class-name}")
    private String driver;

    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.hikari")
    public HikariDataSource dataSource(DataSourceProperties dataSourceProperties) {
        return dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class)
                .build();
    }

    @Bean
    @Primary
    public JdbcTemplate jdbcTemplate(@Qualifier("dataSource") DataSource dataSource,
            JdbcProperties properties) {
        return new JdbcTemplate(dataSource);
    }

    @Bean
    @Primary
    public NamedParameterJdbcTemplate namedParameterJdbcTemplate(
            @Qualifier("jdbcTemplate") JdbcTemplate jdbcTemplate) {
        return new NamedParameterJdbcTemplate(jdbcTemplate);
    }

    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            EntityManagerFactoryBuilder builder, @Qualifier("dataSource") DataSource dataSource) {
        return builder.dataSource(dataSource).packages("test.entity.sybase")
                .persistenceUnit("sybase").build();
    }

    @Bean(name = "transactionManager")
    public PlatformTransactionManager transactionManager(
            @Qualifier("entityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

}


Microsoft SQL Server Configuration:
package test.config;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

import com.zaxxer.hikari.HikariDataSource;

@Configuration
@EnableJpaRepositories(entityManagerFactoryRef = "sqlserverEntityManagerFactory", 
                       transactionManagerRef = "sqlserverTransactionManager", 
                       basePackages = {"test.repository.sqlserver" })
public class SqlServerDbConfig {

    @Value("${sqlserver.datasource.url}")
    private String url;

    @Value("${sqlserver.datasource.username}")
    private String username;

    @Value("${sqlserver.datasource.password}")
    private String sqlPassword;

    @Value("${sqlserver.datasource.driver-class-name}")
    private String sqlDriver;

    @Bean
    @Qualifier("sqlserverDataSource")
    @ConfigurationProperties(prefix = "npa.ai.datasource.hikari")
    public HikariDataSource sqlserverDataSource() {
        return DataSourceBuilder.create().url(url).username(username).password(sqlPassword)
                .driverClassName(sqlDriver).type(HikariDataSource.class).build();
    }

    @Bean
    @Qualifier("sqlserverJdbcTemplate")
    public JdbcTemplate sqlserverJdbcTemplate(@Qualifier("sqlserverDataSource") DataSource sqlserverDataSource) {
        return new JdbcTemplate(sqlserverDataSource);
    }

    @Bean
    @Primary
    public NamedParameterJdbcTemplate namedParameterJdbcTemplate(
            @Qualifier("sqlserverJdbcTemplate") JdbcTemplate jdbcTemplate) {
        return new NamedParameterJdbcTemplate(jdbcTemplate);
    }

    @Bean(name = "sqlserverEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean sqlserverEntityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("sqlserverDataSource") DataSource sqlserverDataSource) {
        return builder.dataSource(sqlserverDataSource).packages("test.entity.sqlserver")
                .persistenceUnit("sqlserver").build();
    }

    @Bean(name = "sqlserverTransactionManager")
    public PlatformTransactionManager sqlserverTransactionManager(
            @Qualifier("sqlserverEntityManagerFactory") EntityManagerFactory sqlserverEntityManagerFactory) {
        return new JpaTransactionManager(sqlserverEntityManagerFactory);
    }

}



Reference
[1] https://scattercode.co.uk/2016/01/05/multiple-databases-with-spring-boot-and-spring-data-jpa/

2019/03/07

[Chrome] JSON Formatter Plugin

Problem
I am using Spring Actuator to monitor our app, gathering metrics, understanding traffic or the state of our database becomes trivial with this dependency.The main benefit of this library is that we can get production grade tools without having to actually implement these features ourselves. 

Actuator is mainly used to expose operational information about the running application – health, metrics, info, dump, env, etc. 

And it will provide information for me with JSON format:

But the JSON is not formatted, how to format the output JSON?


How-To
Install Chrome plugin to fulfill this requirement: https://chrome.google.com/webstore/detail/json-formatter/bcjindcccaagfpapjjmafapmmgkkhgoa/


2019/03/06

[Eclipse] Get the power to write better code with sonarlint

You can install sonarlint plugin to get the power to write better code.
For example, if you forgot to close IO resource properly, you will get this hint:

And it will tell you how to fix this problem:


2019/03/05

[閱讀筆記] 人類大命運 (1/8)


  1.  現在的大多數國家,真正遠遠更嚴重的並不是饑荒,反而是飲食過量。在十八世紀,據說法國王后瑪麗安東尼,曾向挨餓的民眾說,如果沒有麵包可以吃,何不吃蛋糕呢?但今天的窮人真的如此!現今,住在比佛利山莊的有錢人吃生菜沙拉、清蒸豆腐佐紅藜,而住在貧民區的小女生則是大口嚼著美國的國民零食 Twinkie 蛋糕、奇多、漢堡和 pizza2014 年,全球體重過重的人數超過 21 億,營養不良的有 8.5 億。預計到 2030 年,全球會有 50% 的人體重過重。 2010 年,饑荒和營養不良合計奪走約 100 萬人的性命,但肥胖卻讓 300 萬人命喪黃泉。(p.11)
  2. 雖然我們不敢保證,絕不會爆發新一波伊波拉或未知流感病毒的疫情,橫掃全球造成數百萬人身亡,但至少我們不會認為這是不可避免的天然災害。我們反而會認為:這是不可原諒的人為疏失,要求有人為此負起責任。這種批評背後的假設,正是認為人類的知識和工具已經足以防治傳染病,如果疫情仍然失控,原因便是人類的無能,而不是什麼神的憤怒(p.19) 
  3. 在遠古農業社會,人類暴力佔了死亡總數的 15%,而在 20 世紀,暴力事件只佔死亡總數 5%,到了 21 世紀初,更是只佔全球死亡總數約 1%。例如 2012 年,全球約有 5600  萬人死亡,其中 62 萬人死於人類暴力 (戰爭致死 12 萬人、犯罪致死 50 萬人)。相較之下,自殺的人數有 80萬,死於糖尿病更有 150 萬。在現代,糖可比火藥更致命(p.20)
  4. 隨著知識成為最重要的經濟資源,戰爭能帶來的獲利下降;可能發生戰爭的地方,越來越侷限在世界的特定區域 (像是中東和中非),這些地方仍然維持老式的物料導向經濟。例如盧安達在 1998 年入侵鄰國剛果,奪取該國豐富的鈳鉭鐵礦 (Coltan),這是因為此礦產是生產手機與筆記型電腦不可或缺的原料,剛果的蘊藏量佔了全球 80%,盧安達掠奪來的鈳鉭鐵礦,每年可以賺到兩億四千萬美金;相較之下,中國入侵加州奪下矽谷,則無法獲得任何矽礦,矽谷的價值在於人腦裡頭的知識,在中國攻下加州前,所有人都跑光了。(p.21)
  5. 恐怖主義只是得不到真正權力的人,所採取的軟弱策略。恐怖份子通常無力擊敗軍隊、佔領國家,或是破壞整座城市。就本質而言,恐怖主義就是一種表演。恐怖份子安排一場令人驚恐的暴力秀,抓住我們的想像,讓我們以為自己即將再次陷入中世紀那種混亂中。恐怖主義就像是一隻想要大鬧瓷器店的蒼蠅。蒼蠅如此弱小,自己甚至連一紙茶杯都動不了,於是找來一頭牛,鑽到牠耳裡嗡嗡作響,讓牛因為恐懼和憤怒而發狂,破壞整家瓷器店(p.23)
  6. 我們之所以可以成功控制饑荒、瘟疫和戰爭,很大的原因在於驚人的經濟成長帶來豐富的食物、醫藥、能源和原物料。然而,同樣也是因為經濟成長,已經讓地球的生態平和在許多方面失衡,而我們現在才剛開始有所意會。人類對於這項危機承認的很晚,而且至今的努力也不足。(p.26)
  7. 德國理論物理學家 Max Planck 有句名言:「科學在一次一次葬禮中進步。」他所說的是,必需等到一個世代離去,新的理論才有機會剷除舊理論(p.33)
  8. 人們不想總是忙著生產,而是想要幸福快樂。生產之所以重要,是因為能夠為幸福提供物質基礎。生產只是手段,不是目的。在一次又一次的調查中,哥斯大黎加人的生活滿意度都遠高於新加坡人 (新加坡與哥斯大黎加兩國的 GDP 分別為 56,000 14,000 美元)。你想當個生產力高但不太開心的新加坡人,還是當個生產力較低,但心滿意足的哥斯大黎加人?(p.39)
  9. 伊比鳩魯把至善定義成幸福快樂的時候,就曾告誡弟子,快樂是件辛苦的差事,光是物質成就,無法讓我們長久感到滿足。盲目追求金錢、名譽和歡愉,只會讓我們痛苦不堪舉例來說,伊比鳩魯就建議吃喝要適量,性慾要節制。從長遠看來,深厚的友誼會比一夜狂歡,讓人更快樂。當代人顯然比過去的前人更為滿足,雖然已開發國家更為繁榮、舒適及安全,但自殺率卻遠高於傳統社會。(p.39)
  10. 幸福感被罩了一片神秘的玻璃天花板,雖然我們達到了前所未有的成就,幸福感卻未能成長。幸福快樂的天花板有兩大支柱,分別屬於心理層面和生物層面:(p.41~42)
    1. 在心理層面,快樂與否要看你的期望如何,而非客觀條件。光是和平繁榮的生活,並不能讓我們滿意,必須是現實符合期望,才能讓我們滿足。但壞消息是,隨著客觀條件改善,期望也會不斷膨脹。
    2. 從生物層面來說,不管是期望或幸福感,其實都是生物化學機制控制的,而不是由經濟、社會和政治局勢來決定。愉悅或痛苦從來就不是對外在世界事件的反應,而是對自己體內感覺的反應。丟掉工作、離婚或市政府開戰,事件本身並不會讓人受苦。唯一讓人痛苦的,是自己身體裡不愉快的感覺。丟掉工作會引發沮喪,而沮喪才是一種令人不悅的身體感覺。 
  11. 科學也說,並沒有人是因為得到升職、中彩券,甚至是找到真愛而快樂。真正能讓人幸福快樂的,只有一件事、別無其他可能,也就是身體裡的愉悅感覺。如果去年我意外升遷,很有可能雖然現在我還是在這個位置上,但當初聽到消息的愉悅感早已經在幾個小時後煙消雲散。如果想再感受那些美妙的感覺,就得再升遷一次。萬一滿懷希望,卻沒能再升遷,感受到的痛苦和憤怒,可能還遠比當初乾脆一直當個無名小卒來得高(p.42~44)
  12. 人喝酒是為了遺忘;抽大麻是為了感到平靜;用古柯鹼和安非他命是為了感到敏銳且自信;吞搖頭丸能讓人放大感官、感受狂喜;而 LSD 則會讓你踏進一場脫離現實的迷幻夢境。(p.47~48)
  13. 現代經濟要能維持,就需要不斷地、而且是無止境的成長。如果成長停止,經濟不會溫溫順順地平靜下來,而是會轟然崩解。(p.60)
  14. 治療與演化之間,並沒有明確的界線,醫學一開始幾乎總是要拯救那些落在常態下線以下的人,但是同樣的工具和知識,也能用來超越常態的上限威而剛一開始是治療血壓問題,但輝瑞公司驚喜發現,它竟然能醫治陽痿。於是威而鋼讓數百萬人重新獲得正常的性能力;很快地,連沒有陽痿問題的男人也開始服用,好讓自己超越常態、得到過去未曾擁有的性能力。(p.60)
  15. 發生於特定藥物的是,也有可能發生在整體醫藥領域。現代整形外科誕生於第一次世界大戰,當時是 Harold Gillies 在英國 Aldershot 軍醫院,一致創傷,但他在戰後發現,同樣的技術也能用來讓無病無痛、但很醜陋的鼻子,變得更美觀。雖然整形手術仍然繼續協助顏面受傷的病人,但也愈來愈常用來為健康人士增添顏值。到如今,整形外科醫師在私人診所裡荷包滿滿,其明確且唯一的目標,就是要讓健康的人更提升、富有的人再加分。(p.60~61)
  16. 有些複雜系統(例如天氣)是完全無視於我們的預測,但人類發展的過程則會對預測產生反應。事實上,預測越準確,引起的反應就愈多。因此很矛盾的是,隨著我們搜集更多資料、提升運算能力,事件反而會變得更出乎意料而難以預測。知道得愈多,反而能預測的愈少。舉例來說,假設某天,專家解開了經濟的基本法則。這時銀行、政府、投資人和客戶,會立即應用這項新知,展開新的行為,希望能佔到競爭對手的便宜。但令人感嘆的是,只要人們一改變行為模式,新找出來的經濟理論也就立即過時。我們或許能夠找出經濟在過去如何運作,但已經無法在確知經濟在目前如何運行,未來就更別說了。(p.65~66)
  17. 這正是歷史知識的矛盾。知識如果不能改變行為,就沒有絲毫用處。但知識一旦改變行為,本身就立刻失去意義。我們擁有愈多資料、對歷史了解愈深入,歷史的軌跡就改變得愈快,我們的知識也過時得更快。(p.67)
  18. 到了今日,知識增加的速度飛快,理論上,我們應該越來越了解這個世界。然而情況卻正好相反。各種新知識讓經濟、社會和政治的變化加速;為了瞭解究竟發生什麼事,我們加速搜集和累積知識,卻只導致動盪更為加速加劇。於是,我們越來越無法真正瞭解現在、預測未來(p.67)
  19. 歷史學家研究過去,不是為了要重複過去,而是為了從中解放。歷史不僅塑造我們的科技、政治和社會,也塑造我們的思想、恐懼和夢想。正因如此,馬克思主義者才要講述資本主義的歷史,女權主義者才要研究父權社會的形成,非裔美國人要永遠記住奴隸販運的恐怖。他們的目的不是要延續過去,而是要從過去解放。(p.68~69)
  20. 在私人會所和公共建築前面種植一片綠油油草皮的想法,是誕生於中世紀晚期英、法兩國貴族的城堡。到了近代早期,這個習慣已經根深蒂固,成了貴族的商標。想要擁有一片漂亮的草坪,除了有地,還得付出許多心力,特別是以前可沒有自動灑水裝置和割草機,而且草坪並不會產生任何價值。貧窮的農民負擔不起,且不可能把寶貴的土地或時間浪費在草坪上。於是城堡入口處那片完美的草地,就成了無人能造假的身份象徵。草坪越廣闊、修整越完美,就代表這個家族越強盛。如果你拜訪一位公爵,卻看到草坪維護不佳,就知道他有麻煩了(p.71)