首先是定义一个实体类,如下
/*
* 定义用户,通过注解映射到数据库
*/
@Table("user")
public class User {
@Column("id")
private int id;
@Column("username")
private String username;
@Column("nickname")
private String nickName;
@Column("age")
private int age;
@Column("email")
private String email;
@Column("mobile")
private String mobile;
public User(){
//
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getNickname() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
}
上面有类注解和方法注解,分别new一个Annotation,
其中注解里面只有一个值,因此直接用value()声明即可
Table.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*ElementType参数有
* CONSTRUCTOR:构造器的声明
* FIELD:域,属性的声明
* LICAL_VARIABLE:局部变量的声明
* PACKAGE:包声明
* PARAMETER:参数声明
* TYPE:类,接口(包括注解类型)或enum声明
* */
@Target({ElementType.TYPE})
/*
* 需要保存的级别
* SOURCE:注解将被编译器丢掉
* CLASS:注解在class文件中可以使用,会被VM丢掉
* RUNTIME:VM将在运行时也保留注解,因此可以通过反射机制读取注释的信息
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value();
}
Column.java
//定义一个描述用户表属性字段的注解
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 Column {
String value();
}
然后是转换函数
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//将传入的用户信息转换为sql语句
public class ToSql {
public static String query(Object u){
StringBuilder sqlstr=new StringBuilder();
//获取到class
Class c=u.getClass();
// 查看是否包含Table类型的注解
if(!c.isAnnotationPresent(Table.class)){
return null;
}
//如果包含,获取到Table类,并通过此获取到Table类注解
Table table=(Table)c.getAnnotation(Table.class);
String tableName=table.value();
//先将sql语句的前半部分写入
sqlstr.append("SELECT * FROM ").append(tableName).append(" WHERE 1=1");
//获取所有自己声明的属性
Field[] fields=c.getDeclaredFields();
//遍历属性
for (Field field : fields) {
//通过注解中的值来获取属性名(注解中的值应该与属性名相等)
String columnValue=field.getAnnotation(Column.class).value();
//获取属性的get方法的方法名,方法名的写法一般为get+属性名(属性名的第一个字母大写)
String getMethodName="get"+columnValue.substring(0, 1).toUpperCase()+columnValue.substring(1);
//使用反射通过方法名获取方法,并调用invoke方法运行该方法,得到返回值
Object fieldValue=null;
try {
Method getMethod=c.getMethod(getMethodName);
fieldValue=getMethod.invoke(u);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
// TODO Auto-generated catch block
System.out.println("MethodName="+getMethodName);
e.printStackTrace();
}
//因为是遍历所有的方法,所以有些方法是没有赋值的,也就是不需要查找,将其剔除
if(fieldValue==null||((fieldValue instanceof Integer) &&((Integer)fieldValue==0))){
continue;
}
sqlstr.append(" AND ").append(columnValue);
//判断字符串,多个中满足任何一个用IN,并使用''
if(fieldValue instanceof String){
//感觉接口太神奇了
if(((String)fieldValue).contains(",")){
String[] values=((String)fieldValue).split(",");
sqlstr.append(" IN(");
for (String string : values) {
sqlstr.append("'").append(string).append("'").append(",");
}
//删除最后一个","
sqlstr.deleteCharAt(sqlstr.length()-1);
sqlstr.append(")");
}else{
//字符串表示法
sqlstr.append("=").append("'").append(fieldValue).append("'");
}
}else if (fieldValue instanceof Integer) {
sqlstr.append("=").append(fieldValue);
}
}
return sqlstr.toString();
}
}
Test.java测试类
public class Test {
public static void main(String[] args) {
User user=new User();
user.setEmail("2378@134.com,2334@189.com");
System.out.println(ToSql.query(user));
}
}