java 生成sql语句_Java 注解入门 自动生成SQL语句

引言

在用hibernate的时候发现idea能自动生成JavaBean,同时带有一些注解,这引起了我的好奇。当在学习Android的时候,我发现XUtils这个工具包中的DBUtils也能够使用类似hibernate的注解。于是乎在java编程思想中找了找有关注解的用法。

一 注解定义

注解(也称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据。注解来源于C#之类的其他语言。

注解的语法比较简单,除了@符号外,它与java的固有语法一致。javaSE5中内置了三种注解:

@Override:定义覆盖超类,当覆写对应不上被覆盖的方法,编译器发出错误提示。

@Deprecated:当使用了该注解,即表示这个方法已经不推荐被使用。

@SuppressWarnings:关闭不当的编译器警告。

二 基本语法

我们使用自定义的注解对一个方法进行注解:

public class Testable{

public void execute()

{

System.out.println("execute...");

}

@WETest

void taskStart()

{

execute();

}

}

在上边的代码中,我们对taskStart方法使用了注解,接下来我们对WETest注解进行定义:

import java.lang.annotation.*;

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public @interface WETest{}

三 定义注解

我们给上边的注解添加一些内容:

import java.lang.annotation.*;

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public @interface WETest{

public int id();

public String Notes() default "there is no Notes";

}

同样,我们对Testable类使用最新的注解:

public class Testable{

@WETest(id=666)

public void execute()

{

System.out.println("execute...");

}

@WETest(id=666,Notes="this is a method")

void taskStart()

{

execute();

}

}

注解就是这么使用的,当注解内容没有填写时,他会使用默认的值,如execute方法,他没有定义Notes,那么Notes默认值为"there is no Notes"。

四 元注解

我们看到注解上边有两行内容,它们是元注解,专门对注解的解释。元注解一共有四种,分别是:

@Target:表示该注解可以用到哪些地方,ElementType,CONSTRUCTOR构造器声明,FIELD域声明(包括enum实例),LOCAL_VARIABLE局部变量声明,METHOD方法,PACKAGE包,PARAMETER参数,TYPE类、接口或enum。

@Retention:表示需要在什么级别上使用,RetentionPolicy,SOURCE注解会被编译器丢掉,CLASS在class文件中可用会被VM抛弃,RUNTIME在VM运行期也会保留可以通过反射获取注解信息。

@Documented:将注解包含在Javadoc中。

@Inherited:允许子类继承父类中的注解。

五 通过注解反射生成SQL语句

接下来,我用一个例子来解释注解的作用。先编写一些注解定义:

//DBTable.java 用来生成数据表

package annotations;

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

}

//Constraints.java 用来定义约束项

package annotations;

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

}

//PrimaryKey.java 将Constraints中的primarykey定义为真,表示为主键

package annotations;

import java.lang.annotation.*;

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

public @interface PrimaryKey {

Constraints constraints() default @Constraints(primarykey = true);

}

//SQLInteger.java 定义列的类型

package annotations;

import java.lang.annotation.*;

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

public @interface SQLInteger {

String name() default "";

Constraints constraints() default @Constraints;

}

//SQLString.java 定义列的类型

package annotations;

import java.lang.annotation.*;

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

public @interface SQLString {

int value() default 64;

String name() default "";

Constraints constraints() default @Constraints;

}

接下来写一个javabean,使用上述注解:

//User.java

import annotations.Constraints;

import annotations.DBTable;

import annotations.SQLInteger;

import annotations.SQLString;

@DBTable(name="user")

public class User {

@SQLInteger(name="id",constraints = @Constraints(primarykey=true))

public Integer id;

@SQLString(value=30)

public String name;

@SQLString(name="passwd",constraints=@Constraints(allownull=false))

public String password;

/*可以不用

public void setId(Integer id) {

this.id = id;

}

public void setName(String name) {

this.name = name;

}

public void setPassword(String password) {

this.password = password;

}

public Integer getId() {

return id;

}

public String getName() {

return name;

}

public String getPassword() {

return password;

}*/

}

我们看到注解中可以使用注解,在SQLInteger中我们使用了Constraints注解。

接下来我们写一个注解处理器:

//Test.java

import java.lang.annotation.Annotation;

import java.lang.reflect.Field;

import java.util.ArrayList;

import java.util.List;

import java.util.Scanner;

import annotations.Constraints;

import annotations.DBTable;

import annotations.SQLInteger;

import annotations.SQLString;

public class Test {

public static String getConstraints(Constraints con)

{

String constraints = "";

if(!con.allownull())

{

constraints +=" NOT NULL";

}

if(con.primarykey())

{

constraints += " PRIMARY KEY";

}

return constraints;

}

public static void main(String[] args) throws ClassNotFoundException {

Scanner s = new Scanner(System.in);

String name = s.next(); //从控制台输入一个类名,我们输入User即可

Class> cl = Class.forName(name); //加载类,如果该类不在默认路径底下,会报 java.lang.ClassNotFoundException

DBTable dbTable = cl.getAnnotation(DBTable.class); //从User类中获取DBTable注解

if(dbTable == null){ //如果没有DBTable注解,则直接返回,我们写了,当然有

return;

}

String tableName = (dbTable.name().length()<1)?cl.getName():dbTable.name();//获取表的名字,如果没有在DBTable中定义,则获取类名作为Table的名字

List columnDefs = new ArrayList();

for(Field field : cl.getDeclaredFields()) //获取声明的属性

{

String columnName = null;

Annotation[] anns = field.getDeclaredAnnotations();//获取注解,一个属性可以有多个注解,所以是数组类型

if(anns.length < 1)

{

continue;

}

if(anns[0] instanceof SQLInteger) //判断注解类型

{

SQLInteger sInt = (SQLInteger)anns[0];

columnName = (sInt.name().length()<1)?field.getName():sInt.name();//获取列名称与获取表名一样

columnDefs.add(columnName+" INT"+getConstraints(sInt.constraints()));//使用一个方法,自己写的getConstraints(Constraints constraints)获取列定义

}

if(anns[0] instanceof SQLString)

{

SQLString sStr = (SQLString)anns[0];

columnName = (sStr.name().length()<1)?field.getName().toUpperCase():sStr.name();

columnDefs.add(columnName + " VARCHAR("+sStr.value()+")"+getConstraints(sStr.constraints()));

}

}

StringBuilder createCommand = new StringBuilder("CREATE TABLE "+tableName+"(");

for(String columnDef :columnDefs)

{

createCommand.append("\n "+columnDef+",");

}

String tableCreate = createCommand.substring(0,createCommand.length()-1)+"\n);";

System.out.println(tableCreate); //打印出来

}

}

我们可以采用上述方法动态的处理一些数据,例如创建数据表。

六 总结

注意:注解不支持继承例如 extends @xxx。

注解的default默认值不可以为null

使用注解可以减少对xml等外部文件的依赖,使得对类的定义可以在一处实现,避免了一个类两处定义的麻烦。spring和hibernate就采用的这样的方法。

更多文章:http://blog.gavinzh.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java通过反射注解生成对应的SQL语句的步骤如下: 1. 定义注解:首先需要定义一个注解,该注解用于标识字段信息,例如字段名、字段类型、是否为主键等信息。 ``` @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Column { String name(); // 字段名 String type(); // 字段类型 boolean primaryKey() default false; // 是否为主键 } ``` 2. 定义实体类:在实体类的字段上使用上面定义的注解。 ``` public class User { @Column(name = "id", type = "int", primaryKey = true) private int id; @Column(name = "name", type = "varchar") private String name; @Column(name = "age", type = "int") private int age; // 省略getter和setter方法 } ``` 3. 通过反射获取实体类的字段信息:通过反射获取实体类的字段信息,然后读取字段上的注解,获取字段名、字段类型和是否为主键等信息。 ``` public static <T> String generateCreateTableSql(Class<T> clazz) { StringBuilder sb = new StringBuilder(); sb.append("CREATE TABLE IF NOT EXISTS "); sb.append(clazz.getSimpleName()); sb.append("("); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(Column.class)) { Column column = field.getAnnotation(Column.class); sb.append(column.name()); sb.append(" "); sb.append(column.type()); if (column.primaryKey()) { sb.append(" PRIMARY KEY"); } sb.append(","); } } sb.deleteCharAt(sb.length() - 1); sb.append(")"); return sb.toString(); } ``` 4. 生成SQL语句:将读取到的字段信息拼接成对应的SQL语句,例如创建表、插入数据、更新数据等。 ``` public static <T> String generateInsertSql(T entity) { StringBuilder sb = new StringBuilder(); sb.append("INSERT INTO "); sb.append(entity.getClass().getSimpleName()); sb.append("("); Field[] fields = entity.getClass().getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(Column.class)) { Column column = field.getAnnotation(Column.class); sb.append(column.name()); sb.append(","); } } sb.deleteCharAt(sb.length() - 1); sb.append(") VALUES ("); for (Field field : fields) { if (field.isAnnotationPresent(Column.class)) { field.setAccessible(true); Object value = field.get(entity); if (value instanceof String) { sb.append("'"); sb.append(value); sb.append("'"); } else { sb.append(value); } sb.append(","); } } sb.deleteCharAt(sb.length() - 1); sb.append(")"); return sb.toString(); } ``` 以上就是利用反射注解生成对应的SQL语句的步骤,可以根据需要进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值