1. 程式人生 > >Java註解與反射應用的小例子

Java註解與反射應用的小例子

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語句及結果

    由於第一次寫帖子,有點慌亂。在本帖中有任何錯誤歡迎大家指正。