版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fu123123fu/article/details/85039006
需求
实体类与数据库表关联映射,通过在实体类里加自定义注解达到构建sql的目的。
案例
有一个实体类User,里面定义了一些基本属性,我在类上和表名上都加上了我自己定义的注解。注解分别为:@Table和@Column,通过加上注解,我就能知道我要关联的是哪张表以及实体属性对应数据库的哪个字段。
/**
* 创建人:taofut
* 创建时间:2018-12-15 20:51
*/
@Table("user")
public class User{
@Column("id")
private Integer id;
@Column("username")
private String username;
@Column("nickname")
private String nickname;
@Column("age")
private Integer age;
@Column("city")
private String city;
@Column("email")
private String email;
@Column("mobile")
private String mobile;
public Integer getId() {
return id;
}
public void setId(Integer 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 Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
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;
}
}
下面我先创建一下自定义注解@Table和@Column。
/**
* 创建人:taofut
* 创建时间:2018-12-15 21:04
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value();
}
/**
* 创建人:taofut
* 创建时间:2018-12-15 21:04
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String value();
}
最后,我需要通过自定义注解来达到组装sql语句的目的。
/**
* 创建人:taofut
* 创建时间:2018-12-16 13:03
*/
public class Test {
public static void main(String[] args) {
Filter f1=new Filter();
f1.setId(10);//查询id为10的用户
f1.setAge(27);
Filter f2=new Filter();
f2.setUsername("taofut");//查询用户名为taofut的用户
Filter f3=new Filter();
f3.setEmail("1887495****@163.com");//查询邮箱名为这些的用户
String sql1=query(f1);
String sql2=query(f2);
String sql3=query(f3);
System.out.println(sql1);
System.out.println(sql2);
System.out.println(sql3);
}
private static String query(Filter filter) {
StringBuffer sql=new StringBuffer("select * from ");
//1.通过自定义注解拿到表名
//1.1先获取到实例对象的class
Class c=filter.getClass();
Boolean cExist=c.isAnnotationPresent(Table.class);
if(!cExist){
return null;
}
Table tb=(Table)c.getAnnotation(Table.class);
String tableName=tb.value();
sql.append(tableName).append(" where 1=1");
//2.通过自定义注解拿到数据库字段
//2.1先获取所有字段
Field[] fields=c.getDeclaredFields();
for(Field field:fields){
Boolean fExist=field.isAnnotationPresent(Column.class);
if(!fExist){
continue;
}
//2.2取得字段名
Column column=(Column) field.getAnnotation(Column.class);
String fName=column.value();
//2.3取得字段值
String fieldName=field.getName();
String methodName="get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
Object fieldValue=null;
try {
//2.4反射调用get方法,取得字段值
Method m=c.getMethod(methodName);
fieldValue=m.invoke(filter);
if(fieldValue==null || fieldValue.equals("")){
continue;
}
if(fieldValue instanceof Integer){
sql.append(" and ").append(fName).append("=").
append((Integer)fieldValue);
}else if(fieldValue instanceof String){
sql.append(" and ").append(fName).append("=").
append("'").append((String)fieldValue).append("'");
}
} catch (Exception e) {
e.printStackTrace();
}
}
return sql.toString();
}
}
输出结果:
select * from user where 1=1 and id=10 and age=27
select * from user where 1=1 and username=‘taofut’
select * from user where 1=1 and email=‘1887495****@163.com’
总结
归根结底,就是通过反射拿到注解上的值(数据库字段名称),又通过反射去调用get方法获取属性值。sql语句拼接好了,就可以给JDBC去调用了。