Java註解與反射應用的小例子
阿新 • • 發佈:2018-12-23
1.功能介紹
小例子主要完成以下功能,通過Java反射獲取SQL語句,使用MyBatis傳入SQL語句,將資料插入到資料庫中
2.程式碼講解
2.1 自定義註解
首先看一個自定義註解,在此例子中我自定義了兩個註解,一個叫DBTable,另一個是DBColumn。
DBTable用於描述POJO對應的表名。
@Target({ElementType.Type})代表這個註解能用於描述類或者介面。
@Target({ ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) public @interface DBTable { // 用來描述資料庫中表的名稱 String value(); }
DBColmn用於描述POJO中屬性欄位對應資料庫的列名。
@Target({ElementType.Field})代表這個註解用於描述物件的欄位。
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface DBColumn {
// 用來描述表字段的名稱
String value();
}
2.2 實體類
首先給貼出表結構,oper_info表包含四個欄位,分別在oper_id(操作員編號),oper_name(操作員名稱),oper_sex(操作員性別)及oper_role(操作員許可權)。
貼出OperInfo實體類程式碼,在OperInfo的類名上打了個@DBTable註解,它的Value應該與表明oper_info對應。在OperInfo的屬性上都打了@DBColumn,它們的value應該與資料庫中oper_info表的列名相對應。
@DBTable("oper_info")。 public class OperInfo { /** * 1.屬性欄位 */ // 員工編號 @DBColumn("oper_id") private String operId; // 員工姓名 @DBColumn("oper_name") private String operName; // 員工性別 @DBColumn("oper_sex") private int operSex; // 員工角色 @DBColumn("oper_role") private int operRole; /** * 2.生成Getter/Setter方法 */ public String getOperId() { return operId; } public void setOperId(String operId) { this.operId = operId; } public String getOperName() { return operName; } public void setOperName(String operName) { this.operName = operName; } public int getOperSex() { return operSex; } public void setOperSex(int operSex) { this.operSex = operSex; } public int getOperRole() { return operRole; } public void setOperRole(int operRole) { this.operRole = operRole; } /** * 3.生成toString()方法 */ @Override public String toString() { return "OperInfo [operId=" + operId + ", operName=" + operName + ", operSex=" + operSex + ", operRole=" + operRole + "]"; } }
2.3 InsertSqlUtil
InsertSqlUtil是用於將pojo轉換為sql使用。由於只是想說明註解與反射,沒考慮的很全面,只是做了個小示例。public class InsertSqlUtil {
//通過物件獲取SQL語句
public static String getInsertSql(Object o) {
// 1.初始化變數
String invokeResult = null;
String insertFiledName = null;
String insertFiledValue = null;
StringBuilder sqlStrBuilder = new StringBuilder();
// 2.獲取Class
Class<? extends Object> clazz = o.getClass();
// 3.判斷是否含有DBTable.class的註解
if (!clazz.isAnnotationPresent(DBTable.class)) {
// 代表不存在DBTable.class的註解
return invokeResult;
}
// 4.代表存在DBTable.class的註解
DBTable dbTable = (DBTable) clazz.getAnnotation(DBTable.class);
// 獲取資料庫表名
String dbTableName = dbTable.value();
// 5.組裝插入語句,insert into tableName
sqlStrBuilder.append("insert into ").append(dbTableName);
// 6.獲取類屬性欄位(getDeclaredFields可以獲取所有欄位)
Field[] fields = clazz.getDeclaredFields();
// 7.增強for迴圈判斷是否存在DBColumn註解
for (Field field : fields) {
// 判斷是否包含DBColumn註解
if (!field.isAnnotationPresent(DBColumn.class)) {
// 不存在DBColumn註解則跳過檢查
continue;
}
// 獲取列名
DBColumn dbColumn = field.getAnnotation(DBColumn.class);
String dbColumnName = dbColumn.value();
// 獲取pojo欄位名
String fieldName = field.getName();
// 獲取相應欄位的getXXX()方法,將列名首字母大寫,確保可以呼叫OperInfo表中的Getter/Setter方法
String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
Object dbColumnValue = null;
try {
Method getMethod = clazz.getMethod(getMethodName);
dbColumnValue = getMethod.invoke(o);
} catch (Exception e) {
e.printStackTrace();
}
// 進行sql語句拼接
if (dbColumnValue == null) {
// 代表欄位取值為空
continue;
}
if (judgeStringIsNull(insertFiledName)) {
// 代表fileName串為空
insertFiledName = "(" + dbColumnName + ")";
} else {
// 代表fileName串為非空,移掉前一個)
insertFiledName = insertFiledName.substring(0, insertFiledName.length() - 1) + "," + dbColumnName + ")";
}
// 代表欄位取值為非空
if (dbColumnValue instanceof String) {
if (judgeStringIsNull(insertFiledValue)) {
insertFiledValue = "('" + dbColumnValue + "')";
} else {
insertFiledValue = insertFiledValue.substring(0, insertFiledValue.length() - 1) + ",'"
+ dbColumnValue + "')";
}
} else if (dbColumnValue instanceof Integer) {
if (judgeStringIsNull(insertFiledValue)) {
insertFiledValue = "(" + dbColumnValue + ")";
} else {
insertFiledValue = insertFiledValue.substring(0, insertFiledValue.length() - 1) + ","
+ dbColumnValue + ")";
}
}
}
sqlStrBuilder.append(insertFiledName).append(" values ").append(insertFiledValue);
return sqlStrBuilder.toString();
}
// 判斷字串是否為空,返回boolean
public static boolean judgeStringIsNull(String input) {
return ((input == null) || (input.isEmpty()));
}
}
2.4 DAO介面及Mapper檔案
DAO的介面定義public interface OperInfoMapper {
int insertOperInfo(String sql);
}
DAO的Mapper定義
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="org.matcha.dao.OperInfoMapper" >
<insert id="insertOperInfo" parameterType="java.lang.String" >
${value}
</insert>
</mapper>
2.5 測試類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-mybatis.xml")
public class testInsertToDB {
@Autowired
private OperInfoMapper operInfoMapper;
@Test
public void testInsertOperInfoToDB() {
// 第一步:獲取OperInfo物件並賦值
OperInfo operInfo = new OperInfo();
operInfo.setOperId("1");
operInfo.setOperName("234");
operInfo.setOperRole(1);
OperInfo operInfo2 = new OperInfo();
operInfo2.setOperId("2");
operInfo2.setOperName("222");
operInfo2.setOperRole(2);
operInfo2.setOperSex(1);
// 第二步:獲取Insert語句
String operInfoInsertSql1 = InsertSqlUtil.getInsertSql(operInfo);
String operInfoInsertSql2 = InsertSqlUtil.getInsertSql(operInfo2);
// 第三步:呼叫OperInfoMapper使用insert語句
int invokeSql1 = operInfoMapper.insertOperInfo(operInfoInsertSql1);
int invokeSql2 = operInfoMapper.insertOperInfo(operInfoInsertSql2);
// 第四步:列印結果
System.out.println("SQL語句為" + operInfoInsertSql1 + "," + (invokeSql1 > 0 ? "呼叫成功" : "呼叫失敗"));
System.out.println("SQL語句為" + operInfoInsertSql2 + "," + (invokeSql2 > 0 ? "呼叫成功" : "呼叫失敗"));
}
}
執行結果sql語句及結果由於第一次寫帖子,有點慌亂。在本帖中有任何錯誤歡迎大家指正。