使用JDBC实现Oracle或PostgreSQL等数据库的数据源动态切换

1. 首先创建一个连接的Model类

public class JDBC_CONN {
	
	private String base_driver;
	private String base_url;
	private String base_name;
	private String base_pass;
	
	public String getBase_driver() {
		return base_driver;
	}
	public void setBase_driver(String base_driver) {
		this.base_driver = base_driver;
	}
	public String getBase_url() {
		return base_url;
	}
	public void setBase_url(String base_url) {
		this.base_url = base_url;
	}
	public String getBase_name() {
		return base_name;
	}
	public void setBase_name(String base_name) {
		this.base_name = base_name;
	}
	public String getBase_pass() {
		return base_pass;
	}
	public void setBase_pass(String base_pass) {
		this.base_pass = base_pass;
	}
}

2. 在Controller类获得前端传递来的参数

// 根据ID,取得caravel数据集信息和Hawq的结构
	@ResponseBody
	@RequestMapping(value="/getTableInfo/{artId}")
	public Map<String, Object> getTableInfo(@PathVariable String artId, @ModelAttribute JDBC_CONN JDBC_CONN) throws UnsupportedEncodingException {
		
            // 判断前端传递来的驱动是否为空
		if (JDBC_CONN.getBase_driver() != "") {
                // 如果不为空,走自己的动态数据源
			return toMysqlService.selectTableInfo(artId,JDBC_CONN);
		} else {
                // 如果为空走系统启动已经加载的数据源
			return toMysqlService.selectTableInfo(artId,null);
		}
	}

3. ToMysqlService接口(Service接口)

@Service
public interface ToMysqlService {
	Map<String, Object> selectTableInfo(String artId, JDBC_CONN JDBC_CONN);

	Map<String, Object> selectReportInfo(String artId, String artType);
}

4.ToMysqlServiceImpl(Service接口实现类)

// hawq表结构查询
List<Map<String, String>> listStructure = null;
// 判断传入的JDBC_CONN是否为空
if(JDBC_CONN == null) 
    // 为空,则走默认的数据源
    listStructure = daoToHawq.queryForStructure(strTableName);
else 
    // 不为空,则走规定的动态数据源
    listStructure = JDBC_CONN.queryForStructure(strTableName);

5. 在JDBC_CONN的Model类中添加如下方法 queryForStructure()

    // 连接参数
	Connection conn = null;
	PreparedStatement preStmt = null;
	ResultSet rs = null;
	String tableName = strTableName;  // 传入的表名称
	List<Map<String, String>> result = null;  // 定义一个list<map>来存值
	try {
		// 添加数据库驱动
		Class.forName(base_driver);
		String url = base_url;
		conn = DriverManager.getConnection(url,base_name,base_pass);
		// 定义一个List<Map>
		result = new ArrayList<Map<String, String>>();
		
            // 判断前端传入的base_driver中是否存在postgresql,如果存在,需单独处理,如果不是,则是大众数据库的样式进行处理(因为postgresql比较特殊,这种方式不能获取到数据库的表结构) 
		if (!(base_driver.contains("postgresql"))) {
			// Oracle,mysql等查询表结构
			DatabaseMetaData metaData = conn.getMetaData();
			rs = metaData.getColumns(null, "%", tableName, "%");
			while(rs.next()) {
				Map<String, String> mapColumn = new HashMap<String, String>();
				mapColumn.put("name", rs.getString("COLUMN_NAME"));
				mapColumn.put("type", rs.getString("TYPE_NAME"));
				mapColumn.put("size", rs.getString("COLUMN_SIZE"));
				result.add(mapColumn);
			}
				
		} else {  // 否则执行postgresql的查询表结构的方式
			// PostgreSql查询表结构
			String[] str = tableName.split("\\.");  // source.inspur
			String schema = str[0];   // source
			String table = str[1];  // inspur
                        // 根据information_schema.columns表能够查询表结构(此表用来存储表结构)
			String sql = "SELECT * FROM information_schema.columns WHERE TABLE_SCHEMA = '"+schema+"' AND TABLE_NAME = '"+table+"'";
			//执行查询
			preStmt = (PreparedStatement)conn.prepareStatement(sql);
			rs = preStmt.executeQuery();
			while(rs.next()) {
				Map<String, String> mapColumn = new HashMap<String, String>();
				mapColumn.put("name", rs.getString("COLUMN_NAME"));
				mapColumn.put("type", rs.getString("UDT_NAME"));
				// 判断UDT_NAME的值是什么然后赋予不同的值
				if (rs.getString("UDT_NAME").equals("date")) {
					mapColumn.put("size", "13");
				} else if (rs.getString("UDT_NAME").equals("timestamp")) {
					mapColumn.put("size", "29");
				} else {
					mapColumn.put("size", rs.getString("CHARACTER_OCTET_LENGTH"));
				}
					
				result.add(mapColumn);
			}
		}
		
	} catch (ClassNotFoundException e) {
		e.printStackTrace();
	} catch (SQLException e) {
		e.printStackTrace();
	} finally {
		// 释放资源
		try {
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		conn = null;
	}
	return result;
}

6. 就这样,根据调用的返回到前端视图中,这样就连接了自己传入的动态数据源.


补充(核心代码):

1.Oracle,MySQL,DB2等查询表结构的方式:

DatabaseMetaData metaData = conn.getMetaData(); 
rs = metaData.getColumns(null, "%", tableName, "%");  // tableName表示传入的表名称
while(rs.next()) {
	Map<String, String> mapColumn = new HashMap<String, String>();
	mapColumn.put("name", rs.getString("COLUMN_NAME"));  // 获取到COLUMN_NAME列名
	mapColumn.put("type", rs.getString("TYPE_NAME"));  // 类型varchar,int等
	mapColumn.put("size", rs.getString("COLUMN_SIZE"));  // 字段的大小
	}

2.PostgreSQL查询表结构的方式(由于数据库处理机制不一样,查询资料得知postgresql中有一个表专门存各个表结构的信息):

// 保存表结构的表information_schema.columns
String sql = "SELECT * FROM information_schema.columns WHERE TABLE_SCHEMA = '"+schema+"' AND TABLE_NAME = '"+table+"'";
//执行查询
preStmt = (PreparedStatement)conn.prepareStatement(sql);
rs = preStmt.executeQuery();
	while(rs.next()) {
		Map<String, String> mapColumn = new HashMap<String, String>();
                // COLUMN_NAME, UDT_NAME,CHARACTER_OCTET_LENGTH这些字段都是在information_schema.columns 真实存在的
		mapColumn.put("name", rs.getString("COLUMN_NAME")); 
		mapColumn.put("type", rs.getString("UDT_NAME"));
		mapColumn.put("size", rs.getString("CHARACTER_OCTET_LENGTH"));
		result.add(mapColumn);
	}

在这里再说一下: postgresql保存表结构的表是: information_schema.columns

猜你喜欢

转载自blog.csdn.net/qq_40820862/article/details/86319165