閱讀《Think in Java》註解章節後深受啟發,嘗試以自訂註解搭配反射機制,自動產生建立資料表的 SQL 指令。這不僅是練習,更能窺見 Hibernate 等 ORM 框架的核心運作原理。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {
String name() default "";
}
@Target(ElementType.TYPE):限定用於類別、介面、列舉。@Retention(RUNTIME):執行期保留,供反射讀取。name():指定表名,預設為類別名大寫。@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {
boolean primaryKey() default false;
boolean allowNull() default true;
boolean unique() default false;
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger {
String name() default "";
Constraints constraints() default @Constraints;
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLString {
int value() default 0; // VARCHAR 長度
String name() default "";
Constraints constraints() default @Constraints;
}
public class TableCreator {
public static void main(String[] args) {
createTable(Member.class);
}
private static void createTable(Class<?> cl) {
DBTable dbTable = cl.getAnnotation(DBTable.class);
if (dbTable == null) { System.out.println("無 @DBTable 註解"); return; }
String tableName = dbTable.name().isEmpty()
? cl.getSimpleName().toUpperCase() : dbTable.name();
List<String> columnDefs = new ArrayList<>();
for (Field field : cl.getDeclaredFields()) {
Annotation[] anns = field.getDeclaredAnnotations();
if (anns.length == 0) continue;
String columnName = null;
if (anns[0] instanceof SQLInteger) {
SQLInteger sInt = (SQLInteger) anns[0];
columnName = sInt.name().isEmpty()
? field.getName().toUpperCase() : sInt.name();
columnDefs.add(columnName + " INT " + getConstraints(sInt.constraints()));
} else if (anns[0] instanceof SQLString) {
SQLString sStr = (SQLString) anns[0];
columnName = sStr.name().isEmpty()
? field.getName().toUpperCase() : sStr.name();
columnDefs.add(columnName + " VARCHAR(" + sStr.value() + ")"
+ getConstraints(sStr.constraints()));
}
}
StringBuilder sql = new StringBuilder("CREATE TABLE " + tableName + "(");
for (String col : columnDefs) {
sql.append("\n ").append(col).append(",");
}
String ddl = sql.substring(0, sql.length() - 1) + ");";
System.out.println("Table creation SQL for " + cl.getName() + " is :\n" + ddl);
}
private static String getConstraints(Constraints con) {
StringBuilder sb = new StringBuilder();
if (!con.allowNull()) sb.append(" NOT NULL");
if (con.primaryKey()) sb.append(" PRIMARY KEY");
if (con.unique()) sb.append(" UNIQUE");
return sb.toString();
}
}

這個簡易實作揭示了「註解 + 處理器」的核心模式:Hibernate、MyBatis 等框架本質上也是在執行期掃描實體類別的註解(或 XML),動態組裝 SQL。理解此原理,有助於深入掌握 ORM 運作機制,未來擴充自訂 CRUD 邏輯也更得心應手。