解释:
刚刚学习完了反射与注解,简单实现一个统一操作
通过jdbc对数据库进行操作,就插入语句操作来说, 对于不同表,只有那条sql语句是不一样的(其余的获取驱动等等相同操作就不说了),如何能使不同对象调用同一个方法,得到对应的sql插入语句呢?
1.初步实现(反射)
前提:对象的类名,及属性名与数据库的表名,列名是相同的
学生类
public class Student {
private int age;
private String name;
private String sex;
public Student() {
}
public Student(int age, String name, String sex) {
this.age = age;
this.name = name;
this.sex = sex;
}
// 省略getter,setter方法
}
生成sql语句的类
为了检验生成的sql语句是否正确,将语句打印出来
public class Sql {
//表与类统一
public static void session(Object object) {
Class<?> cls = object.getClass();
String name = cls.getSimpleName(); //获取类名
String cols = ""; //列名
String parm = ""; //占位符
Field[] field = cls.getDeclaredFields();
for (Field field2 : field) {
cols += field2.getName()+",";
parm +="?,";
}
cols = cols.substring(0,cols.length()-1);
parm = parm.substring(0,parm.length()-1);
// 拼接sql语句
String sql = "insert into "+name+"("+cols+")values("+parm+")";
System.out.println(sql);
}
}
操作类
public class Test {
public static void main(String[] args) {
Student student = new Student(10, "小红", "男");
Sql.session(student);
}
}
打印结果:
insert into Student(age,name,sex)values(?,?,?)
2.进一步改进(反射,注解)
对象的类名,及属性名与数据库的表名,列名是不相同的
- 表名 student
- 表列名 s_age,s_name,s_sex
- 需要用到反射 及 注解
自定义注解
@Retention(RetentionPolicy.RUNTIME)
public @interface Columns {
String value() default "";
}
改进学生类
@Columns( "student")
public class Student {
@Columns("s_age")
private int age;
@Columns("s_name")
private String name;
@Columns("s_sex")
private String sex;
public Student() {
}
public Student(int age, String name, String sex) {
this.age = age;
this.name = name;
this.sex = sex;
}
// 省略getter,setter方法
}
改进生成sql语句的类
改为运用反射获取对应的值
public class Sql {
public static void session(Object object) {
Class<?> cls = object.getClass();
// 获取加在类上的注解,获取对应值
Columns anno = cls.getAnnotation(Columns.class);
String value1 = anno.value();
String name = value1; //获取 表名
String cols = ""; //列名
String parm = ""; //占位符
Field[] field = cls.getDeclaredFields();
for (Field field2 : field) {
// 获取加在属性上的注解,获取对应值
Columns cns = field2.getAnnotation(Columns.class);
String value = cns.value();
cols += value +",";
parm +="?,";
}
cols = cols.substring(0,cols.length()-1);
parm = parm.substring(0,parm.length()-1);
// 拼接sql语句
String sql = "insert into "+name+"("+cols+")values("+parm+")";
System.out.println(sql);
}
}
使用这个方法,类中必须有注解修饰,不然运行异常
结果
insert into student(s_age,s_name,s_sex)values(?,?,?)
3.最后改进(通用)
改为对有,和没有注解均适用的方法
改进方法:在获取注解前先判断,是否存在注解
方法 : .isAnnotationPresent(Columns.class)
public class Sql {
public static void session(Object object) {
Class<?> cls = object.getClass();
// 判断类上是否存在对应的注解,存在,获取注解,不存在 获取类名
String name;
boolean ap = cls.isAnnotationPresent(Columns.class);
if (ap){
Columns anno = cls.getAnnotation(Columns.class);
String value1 = anno.value();
name= value1; //获取 表名
}else {
name = cls.getSimpleName();
}
String cols = ""; //列名
String parm = ""; //占位符
Field[] field = cls.getDeclaredFields();
for (Field field2 : field) {
String value;
// 获取加在属性上的注解,获取对应值
boolean fas = field2.isAnnotationPresent(Columns.class);
if (fas){
Columns cns = field2.getAnnotation(Columns.class);
value = cns.value();
}else {
value = field2.getName();
}
cols += value +",";
parm +="?,";
}
cols = cols.substring(0,cols.length()-1);
parm = parm.substring(0,parm.length()-1);
// 拼接sql语句
String sql = "insert into "+name+"("+cols+")values("+parm+")";
System.out.println(sql);
}
}
Person类(没有注解)
public class Person {
private String name;
private String id;
private String password;
private String sex;
public Person() {
}
public Person(String name, String id, String password,String sex) {
this.name = name;
this.id = id;
this.password = password;
this.sex = sex;
}
// 省略getter,setter 方法
}
操作类
public class Test {
public static void main(String[] args) {
Student student = new Student(10, "小红", "男");
Sql.session(student);
Person person = new Person("小明", "20174019", "123456","女");
Sql.session(person);
}
}
结果
insert into student(s_age,s_name,s_sex)values(?,?,?)
insert into Person(name,id,password,sex)values(?,?,?,?)