1. 程式人生 > >自定義sql查詢並封裝為指定實體

自定義sql查詢並封裝為指定實體

原理:通過java反射,得到實體屬性對應的欄位名稱及型別,並用原生的jdbc執行查詢並封裝。

直接看原始碼:

1.實體:Zztest

package demo.linj.test;

import java.text.NumberFormat;

public class Zztest {
	
	private String id;
	private String serviceTypeid;
	private Double totlaprice;
	
	@JdbcMapping("ID")
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	@JdbcMapping("SERVICE_TPYEID")
	public String getServiceTypeid() {
		return serviceTypeid;
	}
	public void setServiceTypeid(String serviceTypeid) {
		this.serviceTypeid = serviceTypeid;
	}
	@JdbcMapping("TOTALPRICE")
	public Double getTotlaprice() {
		return totlaprice;
	}
	public void setTotlaprice(Double totlaprice) {
		this.totlaprice = totlaprice;
	}
	
	@Override
	public String toString() {
		return "['id':'"+id+"', 'serviceTypeid':'"+serviceTypeid+"','totalprice':'"+NumberFormat.getCurrencyInstance().format(totlaprice)+"']";
	}
}
2.註解類:JdbcMapping
package demo.linj.test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface JdbcMapping {
	String value() default "";
}
3.訪問連結工具(DAO):LocalJdbcUtils
package demo.linj.test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class LocalJdbcUtils {
	private String driver;
	private String url;
	private String username;
	private String password;
	
	public LocalJdbcUtils(String driver, String url, String username, String password) {
		this.driver = driver;
		this.url = url;
		this.username = username;
		this.password = password;
	}

	/**獲取資料庫連線*/
	private Connection getConnection() {
		Connection conn = null;
		try {
			Class.forName(driver);
			conn = DriverManager.getConnection(url, username, password);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return conn;
	}

	/**得到實體每一個屬性*/
	private HashMap<Field,Object[]> setEntityMap(Class<?> claz) throws Exception {
		HashMap<Field,Object[]> fieldCloumType = new HashMap<Field, Object[]>();
		Field[] fields = claz.getDeclaredFields();
		for (Field field : fields) {
			String fieldName = field.getName();
			String getMethod = "get"+fieldName.substring(0, 1).toUpperCase()+fieldName.substring(1);
			try {
				Method method = claz.getMethod(getMethod, new Class<?>[]{});
				if(method == null) {//如果該屬性沒有對應的get方法,則不處理
					System.out.println("there is no method of 'get' for field '"+fieldName+"'");
					continue;
				}
				JdbcMapping jm = method.getAnnotation(JdbcMapping.class);
				if(jm == null) {
					throw new Exception("The method of 'get' for field named "+claz.getName()+"."+fieldName+" has no use @JdbcMapping annotation");
				}
				fieldCloumType.put(field, new Object[]{jm.value(),method.getReturnType()});//{String,Class<?>}
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			}
		}
		return fieldCloumType;
	}

	/**使用原生態的jdbc查詢*/
	public <E> List<E> findBySql(String sql, Class<? extends E> clz) throws Exception {
		List<E> list = new ArrayList<E>();
		HashMap<Field,Object[]> fieldCloumType = setEntityMap(clz);
		Connection conn = getConnection();
		try {
			PreparedStatement pstmt = conn.prepareStatement(sql);
			ResultSet sets = pstmt.executeQuery();
			while(sets.next()) {
				E z = clz.newInstance();
				for (Field field : fieldCloumType.keySet()) {
					field.setAccessible(true);
					Object[] cloumType = fieldCloumType.get(field);
					if(((Class<?>)cloumType[1]).isAssignableFrom(String.class)) {
						field.set(z, sets.getString((String)cloumType[0]));
					}
					if(((Class<?>)cloumType[1]).isAssignableFrom(Double.class)) {
						field.set(z, sets.getDouble((String)cloumType[0]));
					}
				}
				list.add(z);
			}
			sets.close();
			pstmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return list;
	}
}
=========================

4.測試類:

package demo.linj.test;

import java.util.List;

public class TestJdbcMappingEntity {
	
	public static void main(String[] args) throws Exception {
		LocalJdbcUtils u = new LocalJdbcUtils("oracle.jdbc.driver.OracleDriver", "jdbc:oracle:thin:@localhost:1521:ORCL", "username", "password");
		
		List<Zztest> list = u.findBySql("select * from zztest", Zztest.class);
		for (Zztest zztest : list) {
			System.out.println(zztest);
		}
	}
}

5.輸出結果:

['id':'2', 'serviceTypeid':'f82f28bcad934a5d','totalprice':'¥0.00']
['id':'1', 'serviceTypeid':'f82f28bcad934a5d','totalprice':'¥10.00']
['id':'3', 'serviceTypeid':'f82f28bcad934a5d','totalprice':'¥20.00']
['id':'4', 'serviceTypeid':'f82f28bcad934a5d','totalprice':'¥15.00']

=================================

總結:本例只是一個簡單的使用原生jdbc的模仿,沒有使用AOP等工具類。但原理類似。重點在於JDBC的使用