编写注解处理器拼接SQL

本文介绍了一种使用Java注解处理器自动生成SQL表定义的方法。通过注解处理器读取类上的注解信息,根据这些信息动态生成创建数据库表的SQL语句。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明:本文将采用倒叙方式陈述注解处理器

1.先看结果,抛砖引玉

为annotations.javabean.Member创建的SQL: 
 CREATE TABLE MEMBER(
 FIRSTNAME VARCHAR(30) NOT NULL);
 
为annotations.javabean.Member创建的SQL: 
 CREATE TABLE MEMBER(
 FIRSTNAME VARCHAR(30) NOT NULL,
 LASTNAME VARCHAR(50) NOT NULL);
 
为annotations.javabean.Member创建的SQL: 
 CREATE TABLE MEMBER(
 FIRSTNAME VARCHAR(30) NOT NULL,
 LASTNAME VARCHAR(50) NOT NULL,
 AGE INT NOT NULL);
 
为annotations.javabean.Member创建的SQL: 
 CREATE TABLE MEMBER(
 FIRSTNAME VARCHAR(30) NOT NULL,
 LASTNAME VARCHAR(50) NOT NULL,
 AGE INT NOT NULL,
 HANDLE VARCHAR(30) NOT NULL PRIMARY KEY);
 

2.注解处理器代码(运行时在IDE中进行参数配置对应javabean的全限定名)

package annotations.ImplAnnotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import annotations.database.Constraints;
import annotations.database.DBTable;
import annotations.database.SQLInteger;
import annotations.database.SQLString;

public class TableCreater {
	public static void main(String[] args) throws ClassNotFoundException {
		if(args.length<1){
			System.out.println("参数是注解类型");
			System.exit(0);
		}
		for(String className:args){
			//通过反射机制获取“全类名”对应的Class对象
			Class<?> cl = Class.forName(className);
			//获取DBTable注解
			DBTable dbTable = cl.getAnnotation(DBTable.class);
			//判断是类中是否有DBTable注解
			if(dbTable == null){
				System.out.println("类中没有DBTable注解:"+className);
				continue;
			}
			String tableName = dbTable.name();
			/*
			 * 如果DBTable注解存在,但长度小于1
			 * ("".length()=0),则取对应
			 * 类名作为表名
			 * */
			if(tableName.length() < 1){
				tableName = cl.getName().toUpperCase();
			}
			List<String> columnDefs = new ArrayList<String>();
			/*
			 *1.通过反射机制依次获取类中属性对应的注解
			 *
			 *3.
			 * */
			for (Field field:cl.getDeclaredFields()) {
				String columnName = null;
				Annotation[] anns = field.getDeclaredAnnotations();
				if(anns.length < 1) continue; //not a db table column
				//2.对获取到的注解进行instanceof判断
				if(anns[0] instanceof SQLInteger){
					SQLInteger sInt = (SQLInteger) anns[0];
					//如果没有指定SQLInteger注解的name,则将类中属性名称作为数据库列名
					if(sInt.name().length() < 1)
						columnName = field.getName().toUpperCase();
					else
						columnName = sInt.name();
					columnDefs.add(columnName+" INT"+getConstraints(sInt.constraints()));
				}
				//2.对获取到的注解进行instanceof判断
				if(anns[0] instanceof SQLString){
					SQLString sString = (SQLString) anns[0];
					//空字符串 判断
					if(sString.name().length() < 1)
						columnName = field.getName().toUpperCase();
					else
						columnName = sString.name(); 
					columnDefs.add(columnName+" VARCHAR("+
						sString.value()+")"+getConstraints(sString.constraints()));
				}
				StringBuilder createCommand = new StringBuilder(
						"CREATE TABLE "+tableName+"(");
				String tableCreate = "";
				for (String columnDef : columnDefs) {
					createCommand.append("\n " + columnDef + ",");
					tableCreate = createCommand.substring(
							0,createCommand.length()-1)+");";
				}
				//循环输出每次SQL拼接结果
				System.out.println("为"+className+"创建的SQL: "+
						"\n "+ tableCreate+"\n ");
			}
		}
	}
	
	/*
	 * 获取约束的方法
	 * */
	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;
	}
	
}
3.背注解的javabean

package annotations.javabean;

import annotations.database.Constraints;
import annotations.database.DBTable;
import annotations.database.SQLInteger;
import annotations.database.SQLString;

@DBTable(name="MEMBER")//表名
public class Member {
	//长度30
	@SQLString(30) 
	String firstName;
	
	//长度50
	@SQLString(50) String lastName;
	
	@SQLInteger Integer age;
	
	@SQLString(value=30,constraints=
			@Constraints(primaryKey=true))
	String handle;
	
	static int memberCount;

	public String getFirstName() {
		return firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public Integer getAge() {
		return age;
	}

	public String getHandle() {
		return handle;
	}
	
	@Override
	public String toString(){
		return handle;
	}
	
}

4.注解类

4.1注解类DBTable

package annotations.database;

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 "";
}
4.2注解类Constraints

package annotations.database;

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 allowNull() default false;
	boolean unique() default false;
}

4.3注解类Uniqueness

package annotations.database;

public @interface Uniqueness {
	Constraints constraints()
		default @Constraints(unique=true);
}

4.4注解类SQLString

package annotations.database;

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.5注解类SQLInteger

package annotations.database;

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值