Annotation 使用笔记(二) 注解生成SQL脚本

简述:

《Java 编程思想第四版 》 第20章注解使用笔记


目标: 使用注解生成SQL建表文件


步骤及说明:

1. 项目结构:




2. 声明几种注解

1)  table

DBTable.java

package com.anialy.test.annotation.dbautomaker;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 数据表注解
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @ interface DBTable {
	public String name() default "";
}


2)  SQLInteger

SQLInteger.java

package com.anialy.test.annotation.dbautomaker;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


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


3)  SQLString

SQLString.java

package com.anialy.test.annotation.dbautomaker;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


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



4) Constraints

Constraints.java

package com.anialy.test.annotation.dbautomaker;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 约束条件
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {
	boolean primaryKey() default false;
	boolean unique() default false;
}


3. 绑定Table 实体类Entity

User.java

package com.anialy.test.annotation.dbautomaker.domain;

import com.anialy.test.annotation.dbautomaker.Constraints;
import com.anialy.test.annotation.dbautomaker.DBTable;
import com.anialy.test.annotation.dbautomaker.SQLInteger;
import com.anialy.test.annotation.dbautomaker.SQLString;

@DBTable(name="t_user")
public class User {
	@SQLString(value=36, constraints = @Constraints(primaryKey=true)) 
	private String id; 
	
	// 学号
	@SQLString(value=10, constraints = @Constraints(unique=true))
	private String sn; 
	
	// 姓名
	@SQLString(value=30)
	private String name;
	
	// 年龄
	@SQLInteger 
	private int age;

	public String getId() {
		return id;
	}

	public String getSn() {
		return sn;
	}

	public String getName() {
		return name;
	}

	public int getAge() {
		return age;
	}

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

	public void setSn(String sn) {
		this.sn = sn;
	}

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

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

}


4. SQL Factory 生成sql脚本

SQLFactory.java

package com.anialy.test.annotation.dbautomaker.sqlfactory;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import com.anialy.test.annotation.dbautomaker.Constraints;
import com.anialy.test.annotation.dbautomaker.DBTable;
import com.anialy.test.annotation.dbautomaker.SQLInteger;
import com.anialy.test.annotation.dbautomaker.SQLString;

public class SQLFactory {
	
	
	public SQLFactory(final String className) {
		this.className = className;
	}

	/**
	 * 类名
	 */
	private String className;
	
	/**
	 * 表名
	 */
	private String tableName;
	
	/**
	 * 数据表成员变量的SQL列表
	 */
	private List<String> columnsDefs = new ArrayList<String>();
	
	private String genSQLOfClass() 
			throws ClassNotFoundException{
		Class<?> clazz = Class.forName(className);

		DBTable dbTable = clazz.getAnnotation(DBTable.class);
		
		if(dbTable == null){
			System.out.printf("no such class: %s", className);
			return "";
		}
		
		tableName = dbTable.name();
		
		// If the tableName is empty, then use the class name instead
		if(tableName == null || "".equals(tableName)){
			String fullClassNamePath = clazz.getName().toUpperCase();
			int lastCommaIndex =  fullClassNamePath.lastIndexOf(".");
			tableName = fullClassNamePath.substring(lastCommaIndex + 1);
		}
		
		for(Field field : clazz.getDeclaredFields()){
			String columnName = null;
			Annotation[] anns = field.getDeclaredAnnotations();
			Annotation curAnno = anns[0];
			if(curAnno == null) // no annotation on this field, then continue
				continue;
			else if(curAnno instanceof SQLString){
				SQLString annoString = (SQLString) curAnno;
				columnName = annoString.name();
				if(columnName == null || "".equals(columnName)){
					columnName = field.getName().toUpperCase();
				}
				columnsDefs.add(columnName 
						+ " VARCHAR(" + annoString.value() + ") " 
						+ getConstraints(annoString.constraints())
				);
			}else if(curAnno instanceof SQLInteger){
				SQLInteger annoInt = (SQLInteger)curAnno;
				columnName = annoInt.name();
				if(columnName == null || "".equals(columnName)){
					columnName = field.getName();
				}
				columnsDefs.add(columnName 
						+ " INT "
						+ getConstraints(annoInt.constraints())
				);
			}
		}
		
		
		
		StringBuilder sbd = new StringBuilder();
		sbd.append("CREATE TABLE " + tableName + " (\n");
		for(String columnRow : columnsDefs){
			sbd.append("\t" + columnRow + ",\n");
		}
		// remove trailing comma
		String tbCreate = sbd.substring(0, sbd.length() - 2);
		tbCreate += "\n);\n\n";
		
		return tbCreate;
	}
	
	
	/**
	 * definition of constraints
	 * @param constraints
	 * @return
	 */
	private String getConstraints(Constraints constraints) {
		String constraintsStr = "";
		if(constraints.primaryKey()){
			constraintsStr += "PRIMARY KEY";
		}
		if(constraints.unique()){
			constraintsStr += "UNIQUE";
		}
		return constraintsStr;
	}

	public void outputSQL() throws ClassNotFoundException{
		String createTbSQL = genSQLOfClass();
		if(createTbSQL == null || "".equals(createTbSQL))
			return;
		File file = new File(tableName + ".sql");

		FileOutputStream fos = null;
		
		try {
			fos = new FileOutputStream(file);
			fos.write(createTbSQL.getBytes("utf-8"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(fos != null){
				try {
					fos.flush();
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}





5. 测试类

Test.java

package com.anialy.test.annotation.dbautomaker.test;

import com.anialy.test.annotation.dbautomaker.sqlfactory.SQLFactory;

public class Test {
	
	public static void main(String[] args) throws ClassNotFoundException {
		 new SQLFactory("com.anialy.test.annotation.dbautomaker.domain.User").outputSQL();
	}
}


输出:






附录:

如果使用nio输出,output部分可以这么写

	public void outputSQL() throws IOException, ClassNotFoundException{
		String createTbSQL = genSQLOfClass();
		if(createTbSQL == null || "".equals(createTbSQL))
			return;

		FileChannel fc = new RandomAccessFile(tableName + ".sql", "rw")
                           .getChannel();
		byte[] outputBytes = createTbSQL.getBytes();
		int bytesNum = outputBytes.length;
		ByteBuffer bb = fc.map(FileChannel.MapMode.READ_WRITE, 0, bytesNum);
		bb.put(outputBytes);
		fc.close();
	}





















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值