提出问题
当表中列名有 _ 时,如下表,有些字段有 _:
CREATE TABLE `t_notice` (
`id` VARCHAR(32) NOT NULL COLLATE 'utf8mb4_unicode_ci',
`from_userid` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
`to_userid` VARCHAR(32) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
`msg` VARCHAR(128) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
PRIMARY KEY (`id`)
)
COMMENT='推送消息日志'
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
;
bean为了能够正常运行,名字也必须与 表中列名相同,如下:
public class TNotice2 {
private String id;
private String from_userid;
private String to_userid;
private String msg;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getFrom_userid() {
return from_userid;
}
public void setFrom_userid(String from_userid) {
this.from_userid = from_userid;
}
public String getTo_userid() {
return to_userid;
}
public void setTo_userid(String to_userid) {
this.to_userid = to_userid;
}
}
bean中的属性名也必须有 _,但是这样 不符合 java 成员变量的命名规则
用 DbUtilsBean 类无法完美的解决这种问题
解决
通过自定义 注解,可以指定表中的列名
定义 @Result 注解
package top.malaoshi.jdbc.annotation;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Result {
// 该属性指定列名
String column() default "";
}
修改 IntrospectorUtils 类
取出属性后,继续取出该属性的 @Result 注解,如果有该注解,就取出注解的 column 属性,将该属性作为 Map 中的 key
package top.malaoshi.jdbc;
import top.malaoshi.jdbc.annotation.Result;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class IntrospectorUtils {
/**
* 获取setter方法
* @param clazz
* @return 返回Map,属性名、Result注解的column作为key,setter方法作为value
*/
public static Map<String, Method> getSetMethods(Class clazz) throws IntrospectionException, NoSuchFieldException {
// 使用内省,目的:是反射的简化写法
BeanInfo bi= Introspector.getBeanInfo(clazz); // 返回 BeanInfo,bean的信息
// 将信息取出,放入到数组里
PropertyDescriptor[] pds=bi.getPropertyDescriptors();
// 将属性 和 相关的set方法,放入到map中
Map<String,Method> propertyAndSetterMap = new HashMap();
for( PropertyDescriptor pd : pds){
String propertyName = pd.getName();
if("class".equals(propertyName)){
continue;
}
// 取出该属性对应Field类
Field field = clazz.getDeclaredField(propertyName);
// 取出该属性的 Result 注解
Result resultAnn = field.getAnnotation(Result.class);
String columnName = propertyName;
if(resultAnn!=null){
columnName = resultAnn.column();
}
// 获取 set方法 的信息
Method method = pd.getWriteMethod();
// 如果有 set 方法,就放入到map中
if(method!=null) {
propertyAndSetterMap.put(columnName,method);
}
}
return propertyAndSetterMap;
}
}
测试
定义 bean
成员变量可以不与表中列名相同,但此时要加上 @Result 注解
import top.malaoshi.jdbc.annotation.Result;
public class TNotice {
private String id;
@Result(column = "from_userid")
private String fromUserid;
@Result(column = "to_userid")
private String toUserid;
private String msg;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFromUserid() {
return fromUserid;
}
public void setFromUserid(String fromUserid) {
this.fromUserid = fromUserid;
}
public String getToUserid() {
return toUserid;
}
public void setToUserid(String toUserid) {
this.toUserid = toUserid;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public String toString() {
return "TNotice{" +
"id='" + id + '\'' +
", fromUserid='" + fromUserid + '\'' +
", toUserid='" + toUserid + '\'' +
", msg='" + msg + '\'' +
'}';
}
}
测试类
import top.malaoshi.jdbc.ConnectionFactory;
import top.malaoshi.jdbc.DB;
import top.malaoshi.util.Out;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
public class TestNotice {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//东8时区
String url="jdbc:mysql://localhost:3308/scott?useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
Connection conn = ConnectionFactory.connect("com.mysql.cj.jdbc.Driver"
, url
,"root"
,"");
DB db = new DB(conn);
String sql = "select * from t_notice";
try {
List<Emp> list = db.query(TNotice.class, sql);
Out.elementSep(",\n").printList(list);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}