Chapter 20 - Exercise 1

(2) Implement more SQL types in the database example.


DBTable.java



package com.ciaoshen.thinkinjava.chapter20.db;
import java.lang.annotation.*;

@Target(ElementType.TYPE) // Applies to classes only
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {
    public String name() default "";
}


Constraints.java



package com.ciaoshen.thinkinjava.chapter20.db;
import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {
    boolean primaryKey() default false;
    boolean allowNull() default true;
    boolean unique() default false;
}


SQLString.java



package com.ciaoshen.thinkinjava.chapter20.db;
import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLString {
    int value() default 0;
    String name() default "";
    Constraints constraints() default @Constraints;
}


SQLInteger.java



package com.ciaoshen.thinkinjava.chapter20.db;
import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger {
    String name() default "";
    Constraints constraints() default @Constraints;
}


SQLDecimal.java



package com.ciaoshen.thinkinjava.chapter20.db;
import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLDecimal{
    public int value() default 0;
    public String name() default "";
    public Constraints constraints() default @Constraints;
}


SQLDate.java



package com.ciaoshen.thinkinjava.chapter20.db;
import java.lang.annotation.*;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLDate{
    public int value() default 0;
    public String name() default "";
    public Constraints constraints() default @Constraints;
}


Member.java



package com.ciaoshen.thinkinjava.chapter20.db;

@DBTable(name = "MEMBER")
public class Member {
    @SQLString(30) String firstName;
    @SQLString(50) String lastName;
    @SQLInteger Integer age;
    @SQLDecimal(10) Integer height;
    @SQLDate(20) Long birthday;
    @SQLString(value = 30, constraints = @Constraints(primaryKey = true)) String handle;
    static int memberCount;
    public String getHandle() { return handle; }
    public String getFirstName() { return firstName; }
    public String getLastName() { return lastName; }
    public String toString() { return handle; }
    public Integer getAge() { return age; }
}


Exercise1.java



package com.ciaoshen.thinkinjava.chapter20;
import java.util.*;
import java.lang.reflect.*;
import java.lang.annotation.*;
import com.ciaoshen.thinkinjava.chapter20.db.*;

public class Exercise1 {
    public static void main(String[] args) throws Exception {
        if(args.length < 1) {
            System.out.println("arguments: annotated classes");
            System.exit(0);
        }
        for(String className : args) {
            Class< ? > cl = Class.forName(className);
            
            /**
             *  Table Name
             */
            DBTable dbTable = cl.getAnnotation(DBTable.class);
            if(dbTable == null) {
                System.out.println("No DBTable annotations in class " + className);
                continue;
            }
            String tableName = dbTable.name();
            // If the name is empty, use the Class name:
            if(tableName.length() < 1){
                tableName = cl.getName().toUpperCase();
            }
            
            /**
             *  SQL
             */
            List<String> columnDefs = new ArrayList<String>();
            for(Field field : cl.getDeclaredFields()) {
                String columnName = null;
                Annotation[] anns = field.getDeclaredAnnotations();
                if(anns.length < 1){
                    continue; // Not a db table column
                }
                if(anns[0] instanceof SQLInteger) {
                    SQLInteger sInt = (SQLInteger) anns[0];
                    // Use field name if name not specified
                    if(sInt.name().length() < 1){
                        columnName = field.getName().toUpperCase();
                    }else{
                        columnName = sInt.name();
                    }
                    columnDefs.add(columnName + " INT" + getConstraints(sInt.constraints()));
                }
                if(anns[0] instanceof SQLString) {
                    SQLString sString = (SQLString) anns[0];
                    // Use field name if name not specified.
                    if(sString.name().length() < 1){
                        columnName = field.getName().toUpperCase();
                    }else{
                        columnName = sString.name();
                    }
                    columnDefs.add(columnName + " VARCHAR(" + sString.value() + ")" + getConstraints(sString.constraints()));
                }
                if(anns[0] instanceof SQLDecimal) {
                    SQLDecimal sd = (SQLDecimal) anns[0];
                    // Use field name if name not specified.
                    if(sd.name().length() < 1){
                        columnName = field.getName().toUpperCase();
                    }else{
                        columnName = sd.name();
                    }
                    columnDefs.add(columnName + " DECIMAL(" + sd.value() + ")" + getConstraints(sd.constraints()));
                }
                if(anns[0] instanceof SQLDate) {
                    SQLDate sd = (SQLDate) anns[0];
                    // Use field name if name not specified.
                    if(sd.name().length() < 1){
                        columnName = field.getName().toUpperCase();
                    }else{
                        columnName = sd.name();
                    }
                    columnDefs.add(columnName + " DATE(" + sd.value() + ")" + getConstraints(sd.constraints()));
                }
                StringBuilder createCommand = new StringBuilder("CREATE TABLE " + tableName + "(");
                for(String columnDef : columnDefs){
                    createCommand.append("\n " + columnDef + ",");
                }
                // Remove trailing comma
                String tableCreate = createCommand.substring(0, createCommand.length() - 1) + ");";
                System.out.println("Table Creation SQL for " + className + " is :\n" + tableCreate);
            }
        }
    }
    private static String getConstraints(Constraints con) {
        String constraints = "";
        if(!con.allowNull()){
            constraints += " NOT NULL";
        }
        if(con.primaryKey()){
            constraints += " PRIMARY KEY";
        }
        if(con.unique()){
            constraints += " UNIQUE";
        }
        return constraints;
    }
}



Need Java Developers? Hire Me »

I know Java. Talk is cheap, watch my code.

I live in CANADA now.