2017年12月24日

GSON基礎教學

GSON 前言

JSON是很常見的資料交換格式,在JAVA領域常用處理JSON的函式庫:GSON、FastXML和JSON-B,本章節會以GSON為主,學習目標如下

  • JSON格式說明
  • GSON 套件函式
  • GSON: 物件轉換JSON字串
  • GSON: JSON字串轉換物件

JSON 格式說明

JSON全名為JavaScript Object Notation,它是一種輕量級的資料交換格式,會大為流行的理由,主要是他比傳統用xml更輕巧且容易處理,JSON表達方式物件會用大括弧{},陣列則是用中括號[]。
用JSON字串來表達Employee的物件內容,由JSON字串可以知道物件name、age、sex和salary屬性。

JSON表示員工資料方式:
{“name”:”Jack Bryant”, “age”:18, “sex”:”M”,”salary”:3500.00}

JSON陣列表示方式:
跟我們使用JAVA的陣列方式類似,內容值可以是數字’、文字、布林、陣列、物件、null等等。
範例:
字串: [“紅”、”橙”、”黃”、”綠”、”青”、”藍”、”紫”}
布林: [true, true, false, false, true, true]

GSON 套件函式

Gson為google所發布的函式庫,主要將物件與json字串之間的轉換時方便使用。當我們將JAVA物件轉換成JSON字串稱為序列化,JSON字串轉換至JAVA物件稱為反序列化

enter image description here

GSON: 物件轉換JSON字串

有了JSON基本概念後,我們進入本章重點,首先我們需要建立員工類別(Employee),定義如下

物件 屬性
員工類別 Employee name 名字
age 年紀
sex 性別
salary 薪水
/**
 *  name:員工類別
 */
public class Employee implements Serializable {
    //constructor
    public  Employee(String name, double salary){
        this.name = name;
        this.salary = salary;
    }

    // employ's attribute
    private String name ;
    private int age ;
    private String sex;
    private double salary ;

    //setter and getter
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer() ;
        sb.append("") ;
        sb.append("name:"+name) ;
        sb.append("age:"+age) ;
        sb.append("sex:"+sex) ;
        sb.append("salary:"+salary) ;
        sb.append("") ;
        return sb.toString() ;
    }
   }

完成員工類別後,實際建立一個employee01 的物件,在使用Gson之前需要宣告Gson建構子,範例不管單數還是多數的物件,都是利用同一個toJson()方法來完成序列化轉成JSON字串,所使用起來相當方便。由結果可以發現兩件事情,一、我們發現單數和多數Json字串不同,多數物件顯示會有中括號[物件1、物件2]包括,但是單數沒有。二、Json字串缺少顯示sex屬性值,其將sex屬性列印出來後發現為null值,表示Gson會預先將屬性值為null的預先過濾掉後,才轉成JSON字串。這種方式並不會影響之後反序列處理。後續會有更詳細的Gson字串處理介紹

     /**
 * name : 員工轉json字串測試
 */
public class EmployeeTest {

    public static  void main(String[] arg){
               //單筆
        Employee employee01 = new Employee("bryan",30000);
        Employee employee02 = new Employee("joe",31000);
        employee02.setSex("N");
        Gson gson =  new Gson();
        String jsonStr1 = gson.toJson(employee01);
        String jsonStr2 = gson.toJson(employee01,Employee.class);
        System.out.println("jsonStr1:"+jsonStr1);
        System.out.println("jsonStr2:"+jsonStr2);

        //多筆
        List list = new ArrayList();
        list.add(employee01) ;
        list.add(employee02) ;
        String jsonStr3 = gson.toJson(list);
        System.out.println("jsonStr3:"+jsonStr3);

    }
}

結果:
jsonStr1:{“name”:”bryan”,”age”:0,”salary”:30000.0}
jsonStr2:{“name”:”bryan”,”age”:0,”salary”:30000.0}
jsonStr3:[{“name”:”bryan”,”age”:0,”salary”:30000.0},{“name”:”joe”,”age”:0,”sex”:”N”,”salary”:31000.0}]

物件關係表達

接下來我們將物件關係也加入,看Gson是否可以順利轉換成正確JSON字串,首先我們新增兩個物件:書明細(Book)和借書訂單(Order),之間的關係為員工借書會點選借書訂單系統,去挑選他的書明細,該系統會記錄該員工的姓名以及他點選書單的明細。

物件 屬性
書明細 Book bid 書單號
title書名稱
author 作者
借書訂單 Order orderId 訂單編號
employName 員工名稱
date 日期
bookList 書明細資料
/**
 * name : 書明細
 */
public class Book {
    private String bid;
    private String title;
    private String author;

    public Book(String bid, String title, String author)  {
        this.bid = bid ;
        this.title = title ;
        this.author = author ;
    }
    //setter and getter
    public String getBId() {
        return bid;
    }

    public void setBId(String id) {
        this.bid = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer() ;
        sb.append("") ;
        sb.append("bid:"+bid) ;
        sb.append("title:"+title) ;
        sb.append("author:"+author) ;
        sb.append("") ;
        return sb.toString() ;
    }

}

/**
 * name : 借書訂單
 */
public class Order {
    private String orderId;
    private String employName;
    private Date date;
    private List bookList;
    public Order(String orderId, String employName, Date date,
                 List bookList) {
        super();
        this.orderId = orderId;
        this.employName = employName;
        this.date = date;
        this.bookList = bookList;
    }

    //setter and getter
    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public String getEmployName() {
        return employName;
    }

    public void setEmployName(String employName) {
        this.employName = employName;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public List getBookList() {
        return bookList;
    }

    public void setBookList(ArrayList bookList) {
        this.bookList = bookList;
    }

    public void show() {
        System.out.println("Order information:");
        System.out.println("orderId = " + orderId + "; employName = " + employName
                + "; date = " + date);
        System.out.println("Details: ");
        System.out.println(bookList.toString());
    }
}

employee01藉兩本書分別編號為B0001和B0002,這兩本書,我們把它加入oreder建構子中,再由Gson轉換成JSON字串出來,由結果顯示可以知道該訂單借了幾本書和是哪位員工借走。

/**
 * name : 借書訂單轉json字串測試
 */
public class OrderTest {

    public static  void main(String[] arg){
        //單筆
        Employee employee01 = new Employee("bryan",30000);
        Employee employee02 = new Employee("joe",31000);
        Book book01 = new Book("B0001","水滸傳","施耐庵 ") ;
        Book book02 = new Book("B0002","西遊記","吳承恩 ") ;
        Book book03 = new Book("B0003","三國演義","羅貫中 ") ;
        Book book04 = new Book("B0004","紅樓夢","曹雪芹 ") ;
        List bList = new ArrayList

JSON字串轉換物件

之前員工建立的Json字串,現在介紹如何用Gson來反序列Employee物件,有範例可以知道,Gson幾行就可以將JSON轉成物件化,用起來相當方便。

範例: JSON字串: {“name”:”bryan”,”age”:0,”salary”:30000.0}

/**
 * name: Json to Object 反序列範例
 */
public class EmployeeSTest {

    public static void main(String[] ags){
        Gson gson = new Gson();
        String employ_json = "{\"name\":\"bryan\",\"age\":0,\"salary\":30000.0}" ;
        Employee employee01 =  gson.fromJson(employ_json, Employee.class) ;
        System.out.println(employee01.toString());

    }
}

再來我們試看看List串列看看,是否可以也是跟上面宣告多數的物件相同,複數物件反序列比較麻煩一點,因為反序列需要告訴預先要轉換哪種類別,利用new TypeToken的方式來取得類別的類型,再使用fromJson方法轉回List<Employee>類型。
問題延伸: 但如果遇到泛型要如何解決?

Json字串: [{“name”:”bryan”,”age”:0,”salary”:30000.0},{“name”:”joe”,”age”:0,”sex”:”N”,”salary”:31000.0}]

/**
 * name: Json to Object 反序列範例
 */
public class EmployeeSTest {

    public static void main(String[] ags){
        Gson gson = new Gson();
        String employ_json = "{\"name\":\"bryan\",\"age\":0,\"salary\":30000.0}" ;
        Employee employee01 =  gson.fromJson(employ_json, Employee.class) ;
        System.out.println(employee01.toString());
        System.out.println("=========================List===========================");
        String employs_json = "[{\"name\":\"bryan\",\"age\":0,\"salary\":30000.0},{\"name\":\"joe\",\"age\":0,\"sex\":\"N\",\"salary\":31000.0}]";
        Type collectionType = new TypeToken

參考資料

  1. https://bng86.gitbooks.io/android-third-party-/content/gson.html
  2. http://j796160836.pixnet.net/blog/post/30530326-%E7%9E%AD%E8%A7%A3json%E6%A0%BC%E5%BC%8F
  3. http://blog.csdn.net/zzp_403184692/article/details/8266575

2017年12月20日

H2資料庫(2)-資料庫操作

H2 操作介紹

在上一章節我們大致上介紹了H2資料庫的特性和安裝方式,本章節會實際使用JAVA來連結資料庫,做新增、刪除、修改和查詢等語法操作,讓大家對H2可以有更進一步的了解。

實際操作

  • 新增員工資料表
    我們今天來新增一個資料表為員工(EMPLOYEE),員工有職工編號、姓名、姓名、性別和是否在職。首先貼上新增資料表的語法(如下),然後按下RUN按鈕,就會出現下面訊息,如果左側欄位有出現EMPLOYY表示新增資料表成功
    新增資料表EMPLOYEE
    CREATE TABLE EMPLOYEE (
        ID BIGINT IDENTITY PRIMARY KEY,
        NAME VARCHAR(100),
        SALARY DOUBLE,
        SEX  VARCHAR(1),
        ISQUIT BOOLEAN
    );
  • 新增一筆員工資料
    新增員工資料
insert into EMPLOYEE (name, salary, sex, isquit) values ('bryan',30000,'N',0) ;
  • 查詢該名員工資料
    查詢該名員工資料
select * from  EMPLOYEE 
  • 修改該名員工資料
    修改該名員工資料
update employee  set name='', sex='M' where id='1'  ; 
  • 刪除該名員工資料
    刪除該名員工資料
delete employee  where id='1'  

2017年12月17日

H2資料庫(1)-基本安裝與介紹

H2資料庫介紹

H2為嵌入式資料庫,使用java開發,跨平台且內含資料庫管理介面,好處開發階段方便開發人員使用。

比較

詳細比較表: http://www.h2database.com/html/features.html#comparison
由圖比較可以知道,H2比其他資料庫更為優勢,以下會介紹開發時常用的模式:
enter image description here

  • 嵌入式模式Embedded Mode
    嵌入式資料庫會與應用程式共用同一JVM底層,在這個模式下persistent或是in-memory資料庫都支援,也沒有連線數的限制。但壞處是只可以給該應用程式使用,其他人無法直接存取資料庫。

  • 伺服器模式 Server Mode
    外部應用程式可以藉由JDBC或是OBC的方式連結該資料庫,它也支援persistent或是in-memory資料庫,也沒有連線數的限制。

  • 混合模式 Mixed Mode
    同時有嵌入式與伺服器的模式去讓外部應用程式連線或是自己應用程式連線。

安裝H2 database

官方網站: http://www.h2database.com/html/main.html

  1. 下載安裝程式
    出現安裝連結,本次範例使用Windows installer 的安裝連結

  2. 下載安裝程式後,點擊兩下,進入安裝畫面,按”下一步”

  3. 一直按”下一步”後,會出現”完成”

  4. 安裝完成後,會出現一個說明網頁,你可以點選Quickstart 它會告訴你,如何進入DBRMS畫面以及開啟資料庫服務

  5. 開啟windows的視窗圖示,執行 H2 Console後,會執行H2資料庫

  6. 進入DBRMS的登入畫面,使用者預設為”SA”,密碼為空值”“,按下”connect”進入,SQL命令中心

  7. 登入後,可以在空白處執行SQL語法

8.大致上安裝H2資料庫滿快速,操作畫面也是很好上手,如果系統在開發階段個人覺的滿推薦給大家使用看看。

參考

  1. H2官方網站

2017年12月9日

JavaBean 和POJO

前言

今天介紹JavaBean和POJO的不同,這兩個名詞在JAVA文章常常被拿來使用以及討論。在JDK1.1時候釋出才有的一個標準架構,很多時候常常被搞混,所以我們特別開闢一章來加以討論。POJO規範在企業級應用已經廣大的被使用的規範。

解釋

  1. POJO : 全名為Plain-old-Java-object,只需要繼承Object就可以,沒有特定規定,只要建立的類別有setter/getter方法都可以稱為POJO
  2. JavaBean: JavaBean通常用來封裝多個物件成為單獨物件使用,規範比較嚴格,規則如下
規則 說明
1 需要實作序列(Serializable/Externalizable)
2 不能有參數的建構子( no-arg constructor)
3 需要有公用setter/getter
4 屬性必須要私人(private)
5 屬於特定POJO規則

比較

  • 所有的JavaBean都為POJO,但是所有的POJO不一定為JavaBean
  • 都可以當作重複元件
  • 都必須序列化
  • 特性都為可用性、易用性和持久化使用
  • -

應用

由圖我們可以知道POJO在應用程式中,主要用來存取資料庫資料達到持久化的目的,並提供給商業邏輯流程處理使用。這種POJO的架構提供程式人員開發時的可以很有規則將資料封裝並加以使用。

POJO的角色

範例1. JavaBean(以員工為實例)
JavaBean建立員工物件,可以發現Employee物件建構子沒有任何參數,屬性為私有化並setter/getter的命名方式。

//實作序列化
public class Employee implements java.io.Serializable{  

private int id;  
private String name;

//無參數建構子
public Employee(){} 

//以下實作setter/getter 
public void setId(int id){this.id=id;}  
public int getId(){return id;}  
public void setName(String name){this.name=name;}  
public String getName(){return name;}  

}

範例2. POJO(以員工為實例)
POJO建構子參數化,有此可以知道name, id, salary為建構子的參數使用。

public class Employee
{

   String name;
   public String id ;
   private double salary;
   public Employee(String name, String id, 
                            double salary)
   {
       this.name = name;
       this.id = id;
       this.salary = salary;
   }

   public String getName()
   {
       return name;
   }

   public String getId()
   {
       return id;
   }

   public Double getSalary()
   {
       return salary;
   }
}

參考

  1. http://www.geeksforgeeks.org/pojo-vs-java-beans/

JavaBean 和POJO

前言

今天介紹JavaBean和POJO的不同,這兩個名詞在JAVA文章常常被拿來使用以及討論。在JDK1.1時候釋出才有的一個標準架構,很多時候常常被搞混,所以我們特別開闢一章來加以討論。POJO規範在企業級應用已經廣大的被使用的規範。

解釋

  1. POJO : 全名為Plain-old-Java-object,只需要繼承Object就可以,沒有特定規定,只要建立的類別有setter/getter方法都可以稱為POJO
  2. JavaBean: JavaBean通常用來封裝多個物件成為單獨物件使用,規範比較嚴格,規則如下
規則 說明
1 需要實作序列(Serializable/Externalizable)
2 不能有參數的建構子( no-arg constructor)
3 需要有公用setter/getter
4 屬性必須要私人(private)
5 屬於特定POJO規則

比較

  • 所有的JavaBean都為POJO,但是所有的POJO不一定為JavaBean
  • 都可以當作重複元件
  • 都必須序列化
  • 特性都為可用性、易用性和持久化使用
  • -

應用

由圖我們可以知道POJO在應用程式中,主要用來存取資料庫資料達到持久化的目的,並提供給商業邏輯流程處理使用。這種POJO的架構提供程式人員開發時的可以很有規則將資料封裝並加以使用。

POJO的角色

範例1. JavaBean(以員工為實例)
JavaBean建立員工物件,可以發現Employee物件建構子沒有任何參數,屬性為私有化並setter/getter的命名方式。

//實作序列化
public class Employee implements java.io.Serializable{  

private int id;  
private String name;

//無參數建構子
public Employee(){} 

//以下實作setter/getter 
public void setId(int id){this.id=id;}  
public int getId(){return id;}  
public void setName(String name){this.name=name;}  
public String getName(){return name;}  

}

範例2. POJO(以員工為實例)
POJO建構子參數化,有此可以知道name, id, salary為建構子的參數使用。

public class Employee
{

   String name;
   public String id ;
   private double salary;
   public Employee(String name, String id, 
                            double salary)
   {
       this.name = name;
       this.id = id;
       this.salary = salary;
   }

   public String getName()
   {
       return name;
   }

   public String getId()
   {
       return id;
   }

   public Double getSalary()
   {
       return salary;
   }
}

參考

  1. http://www.geeksforgeeks.org/pojo-vs-java-beans/

2017年12月6日

Java Reflection(反射機制)之一

Java Reflection -1 (反射機制)

Java Reflection最著名例子就是Spring,它帶來XML和Reflection的結合,可以讓開發者可以動態配置資訊、生成物件或是操過物件,何種情況需要使用Java 反射? 讓我們想一想,有些情況是否需要外部的資訊來決定程式的邏輯或是資料,或是有些情況系統之間希望保持低偶合關係。這些你都可以使用反射機制來完成,例如系統可以提供plugin的功能,來擴充系統的檢查功能,這時候可以利用反射不失為一個辦法。

Java Bean 反射範例

POJO物件 以Employee為例一個反射的對象,我們會介紹利用JAVA的反射設機制,如何將類別解析與載入內容。在一個class類架構會有: Method方法、Field屬性、Constructor建構子,如何分別解析並載入內容,是本章節的重點。

/*
*  name: 員工類別的POJO
*/
public class Employee{

    public  Employee(String id){
        this.id = id ;
    }

    public  Employee(String id, String cname){
        this.id = id ;
        this.cname = cname ;
    }

    private String id ; 
    private String cname ; 
    private String sex ;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getCname() {
        return cname;
    }
    public void setCname(String cname) {
        this.cname = cname;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    } 

    @Override
    public String toString() {
         return "id:"+id+",cname:"+cname+", sex:"+sex ; 
    }
}

類別反射與載入

類別反射是當我需要使用的類別時,我才做載入的動作,也稱為動態載入。如果是程式啟動時就載入,缺點比較耗資源。所以動態載入會讓系統資源更有效的運用。首先 java.lang.Class 物件代表 在運行時所載入的類別或介面實例,使用Class類別可以取得類別的資訊或是生成實例。

  • Class類別API
函式 說明
public static Class forName(String className) 類別的對象
public T newInstance() 返回一個生成實例
public class TestClass01 {
    public static void main(String[] args) {

        Class<?> c1 = Employee.class ; 
        System.out.println("c1-->"+c1);

        try {
            Class<?> c2 = Class.forName("com.tw.refleciton.Employee") ;
            System.out.println("c2-->"+c2);
            System.out.println("c2-->"+c2.getName());
            System.out.println("c2-->"+c2.getSimpleName());
            System.out.println("c2-->"+c2.getEnclosingClass());
        } catch (ClassNotFoundException e) {

            e.printStackTrace();
        }
    }
}
public class TestClass02 {
    public static void main(String[] args) {

        try {
            Class<?> c3 = Class.forName("com.tw.refleciton.Employee") ;
            Object o1 = c3.newInstance() ; 
            System.out.println("c3-->"+c3);
            System.out.println("o1-->"+o1);

        } catch (ClassNotFoundException e) {

            e.printStackTrace();
        } catch (InstantiationException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        }
    }
}

建構子載入

  • Constructor类API
函式 說明
Constructor[] getConstructors() 取得該類別的建構子陣列
Constructor getConstructor(Class… parameterTypes) 符合參數類別,取得建構子對象
T newInstance(Object… initargs) 將內容值設定建構子並生成實例
/*
* name: 取得建構子資訊
*/
public class TestClass03 {
    public static void main(String[] args) {

        try {
            Class<?> c3 = Class.forName("com.tw.refleciton.Employee") ;
            Constructor<?>[] cs = c3.getConstructors();
            for(Constructor<?> c : cs ){
                System.out.print(c.getName()+", parameter size:"+c.getParameterTypes().length);
                Class<?>[] parameters = c.getParameterTypes();
                int i=1 ; 
                if(parameters!=null && parameters.length>0){
                    for(Class<?> p : parameters){
                        System.out.print(",parameter"+i+":"+p.getName()+" , ");
                        i++; 
                    }
                }
                System.out.println();

            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
結果
com.tw.refleciton.Employee, parameter size:2,parameter1:java.lang.String , ,parameter2:java.lang.String ,
com.tw.refleciton.Employee, parameter size:1,parameter1:java.lang.String ,
/*
 * name:有參數化建構子
 * 利用建構子參數化宣告,必須有參數初始化建構子
 */
public class TestClass04 {
    public static void main(String[] args) {
        try {
            Class<?> c = Class.forName("com.tw.refleciton.Employee") ;
            Constructor<?> cs = c.getConstructor(String.class, String.class);
            Object o = cs.newInstance("0001", "丁大幅") ; 
            System.out.println(o.toString());

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        } 
    }
}
結果
id:0001,cname:丁大幅, sex:nul

屬性載入

  • 屬性常用的API
函式 說明
Field[] getDeclaredFields() 取得所有屬性
Field getDeclaredField(String name) 取得指定的屬性
void set(Object obj, Object value) 設定屬性的新內容值
Object get(Object obj) 取得屬性的內容值
void setAccessible(boolean flag) 設定該屬性是否可以訪問true: 可以訪問、false : 不可以訪問
boolean isAccessible() 該屬性是否可以訪問true: 可以訪問、false : 不可以訪問


/**
 * name:解析field的欄位名稱
 */
public class TestClass05 {

    public static void main(String[] args) {

        try {
            Class<?> c5 = Class.forName("com.tw.refleciton.Employee") ;
            Field[] fs = c5.getDeclaredFields() ; 
            if(fs.length>0){
                for(Field f: fs){
                    System.out.println("field:"+f.getName());
                }

            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
結果
name:sex,value –>> 男id:0002,cname:王大明, sex:男

參考

  1. https://github.com/JustinSDK/JavaSE6Tutorial/blob/master/docs/CH16.md
  2. Java反射机制连载(1)– JavaBean
  3. Java反射机制连载(2)– Class类
  4. Java反射机制连载(3)– Constructor类
  5. Java反射机制连载(4)– Field类
  6. Java反射机制连载(5)– Method类
  7. Java反射机制连载(6)– PropertyDescriptor类
  8. Java反射机制连载(7)– 使用反射实现的ORM持久层框架 attachment
  9. Java反射机制连载(7)– 使用反射实现的ORM持久层框架 attachment
  10. Java反射机制连载(9)– 自定义持久层框架之JdbcOperations接口