手撸 SQL to mongodb jdbc driver 玩具

优点闲余时间,于是手撸了一个 Sql to mongodb 的jdbc 驱动,实现简单sql语句查询删除修改mongodb。就是个玩具。

这里用到 jsqlparser 1.2 , bson 3.11, mongodb-driver 3.11 。

这个具备简单增删改查功能的jdbc驱动需要建立4个类分别实现 Driver, Connection, Statement, ResultSet 这四个接口。

具体的实现原理不多说了,反正有代码,斟杯茶,慢慢看,贴出的代码是需要增加的,不需要改动的就不贴了,俺不是写小说的,不做靠字数骗钱事,下面贴代码:

Driver:

public class MongoDBDriver implements Driver {
	
    private final static String connectStrPrefix = "jdbc:mongo:";

	@Override
	public Connection connect(String url, Properties info) throws SQLException {
		if (!acceptsURL(url)) {
		    return null;
		}
		String mongoUrlStr = url.replace(connectStrPrefix, "mongodb:");
		
		
		return new MongoDBConnection(mongoUrlStr);
	}

	private boolean checkConnetionUrl(String url){
		String tempUrlStr = url.replace(connectStrPrefix, "http:");
		URI tempUrl = null;
		try {
			tempUrl = new URI(tempUrlStr);
		} catch (URISyntaxException e) {
			return false;
		}
		return tempUrl==null?false:true;
	}
	
	@Override
	public boolean acceptsURL(String url) throws SQLException {
		if(url.startsWith(connectStrPrefix) && checkConnetionUrl(url) ){
			return true;
		}
		return false;
	}

	@Override
	public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {

		DriverPropertyInfo propInfos[] = new DriverPropertyInfo[0];

		return propInfos;
	}


    static {
		try {
		    DriverManager.registerDriver(new MongoDBDriver());
		} catch (Exception e) {
		}
    }
    


}

Connection

public class MongoDBConnection implements Connection {
	
	private String mongoDBConnString = null;
	private MongoClient mongoClient = null;
	private MongoClientURI mongoClientURI = null;
	private MongoDatabase mongoDatabase = null;
	
	public MongoDBConnection(String connstr){
		mongoDBConnString = connstr;
		mongoClientURI = new MongoClientURI(connstr);
		mongoClient = new MongoClient(mongoClientURI);
		mongoDatabase = mongoClient.getDatabase(mongoClientURI.getDatabase());
	}

	@Override
	public Statement createStatement() throws SQLException {
		
		return new MongoDBStatement(mongoDatabase);
	}


}

Statement

public class MongoDBStatement implements Statement {
	
	private MongoDatabase mongoDatabase = null;
		
	public MongoDBStatement(MongoDatabase database){
		mongoDatabase = database;
	}


	@Override
	public ResultSet executeQuery(String sql) throws SQLException {
		SearchRelateDatas searchRelateDatas = new SearchRelateDatas();
		net.sf.jsqlparser.statement.Statement statement = parseSql(sql);
		if(statement==null){
			throw new SQLException("Parse sql error");
		}
		if(statement instanceof Select){
			PlainSelect selectBody = (PlainSelect)((Select) statement).getSelectBody();
			
			Table fromItem = (Table) selectBody.getFromItem();
			
			searchRelateDatas.collection = mongoDatabase.getCollection(fromItem.getName());
			searchRelateDatas.columns = new ArrayList<String>();
			
			final List<SelectItem> list = selectBody.getSelectItems();
			for (int i = 0; i < list.size(); i++) {
				if (list.get(i) instanceof AllColumns) {
					AllColumns allColumns = (AllColumns) list.get(i);
					searchRelateDatas.columns.add(allColumns.toString());
				} else if (list.get(i) instanceof SelectExpressionItem) {
					SelectExpressionItem sei = (SelectExpressionItem) list.get(i);
					Column c = (Column) sei.getExpression();
					//System.out.println(c.getColumnName());
					searchRelateDatas.columns.add( c.getColumnName() );
				}
			}
			
			Expression where = selectBody.getWhere();
			if(where!=null){
				searchRelateDatas.searchCondition = ParseSqlText.parseWhereStament(where);
			}
			if(searchRelateDatas.searchCondition!=null){
				searchRelateDatas.founds = searchRelateDatas.collection.find(searchRelateDatas.searchCondition);
			}else{
				searchRelateDatas.founds = searchRelateDatas.collection.find();
			}
			return new MongoDBResultSet(searchRelateDatas);
		}
		return null;
	}

	@Override
	public int executeUpdate(String sql) throws SQLException {
		net.sf.jsqlparser.statement.Statement statement = parseSql(sql);
		if(statement==null){
			throw new SQLException("Parse sql error");
		}
		if(statement instanceof Drop){
			Drop drop = (Drop) statement;
			mongoDatabase.getCollection(drop.getName().getName()).drop();
		}else if (statement instanceof Truncate) {
			Truncate truncate = (Truncate) statement;
			truncate.getTable().getName();
			mongoDatabase.getCollection(truncate.getTable().getName()).deleteMany(new Document());
		}else if (statement instanceof Update) {
			Update updateStament = (Update) statement;
			Table table = (Table) updateStament.getTables().get(0);
			MongoCollection<Document> collection = mongoDatabase.getCollection(table.getName());
			List<Column> columnList = updateStament.getColumns();
			List<Expression> exprList = updateStament.getExpressions();
			Document updateDoc = new Document();
			for(int i=0; i<columnList.size(); ++i){
				Column updateColumn = columnList.get(i);
				Expression expr = exprList.get(i);
				ParseSqlText.addNameValueToDoc(updateDoc, updateColumn.getColumnName(), expr);
			}
			Expression where = updateStament.getWhere();
			Document searchCondition = null;
			if(where!=null){
				searchCondition = ParseSqlText.parseWhereStament(where);
			}else{
				searchCondition = new Document();
			}
			collection.updateMany(searchCondition, new Document("$set", updateDoc));
		} else if (statement instanceof Insert) {
			Insert insertStament = (Insert) statement;
			MongoCollection<Document> collection = mongoDatabase.getCollection(insertStament.getTable().getName());
			List<Column> columnList = insertStament.getColumns();
			List<Expression> exprList = ((ExpressionList)(insertStament.getItemsList())).getExpressions();
			Document insertDoc = new Document();
			for(int i=0; i<columnList.size(); ++i){
				Column setColumn = columnList.get(i);
				Expression expr = exprList.get(i);
				ParseSqlText.addNameValueToDoc(insertDoc, setColumn.getColumnName(), expr);
			}
			collection.insertOne(insertDoc);
		} else if (statement instanceof Delete) {
			Delete deleteStament = (Delete) statement;
			MongoCollection<Document> collection = mongoDatabase.getCollection(deleteStament.getTable().getName());
			Expression where = deleteStament.getWhere();
			Document searchCondition = null;
			if(where!=null){
				searchCondition = ParseSqlText.parseWhereStament(where);
			}else{
				searchCondition = new Document();
			}
			collection.deleteMany(searchCondition);
		}
		return 0;
	}

	private net.sf.jsqlparser.statement.Statement parseSql(String sql){
		try {
			return CCJSqlParserUtil.parse(sql);
		} catch (JSQLParserException e) {
		}
		return null;
	}


}

ResultSet

public class MongoDBResultSet implements ResultSet, ResultSetMetaData {
	
	private SearchRelateDatas founds = null;
	private MongoCursor<Document> cursor = null;
	private Document currRecord = null;
	
	public MongoDBResultSet(SearchRelateDatas f){
		founds = f;
		cursor = f.founds.cursor();
	}

	@Override
	public int getColumnCount() throws SQLException {
		int totalColumn = 0;
		for(int i=0; i<founds.columns.size(); ++i){
			if("*".equals(founds.columns.get(i))){
				totalColumn += founds.founds.first().size();
			}else{
				++totalColumn;
			}
		}
		return totalColumn;
	}


	@Override
	public String getColumnName(int column) throws SQLException {
		return (String)(currRecord.keySet().toArray()[column]);
	}


	@Override
	public boolean next() throws SQLException {
		
		currRecord = cursor.hasNext()?cursor.next():null;
		return currRecord==null?false:true;
	}

	@Override
	public void close() throws SQLException {
		cursor.close();
	}


	@Override
	public String getString(int columnIndex) throws SQLException {
		return currRecord.getString(currRecord.keySet().toArray()[columnIndex]);
	}

	@Override
	public boolean getBoolean(int columnIndex) throws SQLException {
		return currRecord.getBoolean(currRecord.keySet().toArray()[columnIndex]);
	}

	@Override
	public int getInt(int columnIndex) throws SQLException {
		return currRecord.getInteger(currRecord.keySet().toArray()[columnIndex]);
	}

	@Override
	public long getLong(int columnIndex) throws SQLException {
		return currRecord.getLong(currRecord.keySet().toArray()[columnIndex]);
	}

	@Override
	public double getDouble(int columnIndex) throws SQLException {
		return currRecord.getDouble(currRecord.keySet().toArray()[columnIndex]);
	}


	@Override
	public Date getDate(int columnIndex) throws SQLException {
		return (Date)currRecord.getDate(currRecord.keySet().toArray()[columnIndex]);
	}


	@Override
	public String getString(String columnLabel) throws SQLException {
		return currRecord.getString(columnLabel);
	}

	

	@Override
	public int getInt(String columnLabel) throws SQLException {
		return currRecord.getInteger(columnLabel);
	}

	@Override
	public long getLong(String columnLabel) throws SQLException {
		return currRecord.getLong(columnLabel);
	}

	@Override
	public double getDouble(String columnLabel) throws SQLException {
		return currRecord.getDouble(columnLabel);
	}

	
}

SearchRelateDatas

public class SearchRelateDatas {
	public List<String> columns;
	public Document searchCondition;
	public MongoCollection<Document> collection;
	public FindIterable<Document> founds;

}

ParseSqlText

public class ParseSqlText {
	
	public static Document buildBetWeenCondition(Between betweenExpr){
		Document betweenVal = null;
		Column column = (Column)betweenExpr.getLeftExpression();
		Expression startExpr = betweenExpr.getBetweenExpressionStart();
		Expression endExpr = betweenExpr.getBetweenExpressionEnd();
		if(startExpr instanceof LongValue){
			betweenVal = new Document(column.getColumnName(), 
					new Document("$gte", ((LongValue)startExpr).getBigIntegerValue())
					.append("$lte", ((LongValue)endExpr).getBigIntegerValue()));
		} else if(startExpr instanceof DoubleValue){
			betweenVal = new Document(column.getColumnName(), 
					new Document("$gte", ((DoubleValue)startExpr).getValue())
					.append("$lte", ((DoubleValue)endExpr).getValue()));
		}else if(startExpr instanceof StringValue){
			betweenVal = new Document(column.getColumnName(), 
					new Document("$gte", ((StringValue)startExpr).getValue())
					.append("$lte", ((StringValue)endExpr).getValue()));
		}else if(startExpr instanceof DateValue){
			betweenVal = new Document(column.getColumnName(), 
					new Document("$gte", ((DateValue)startExpr).getValue())
					.append("$lte", ((DateValue)endExpr).getValue()));
		}else if(startExpr instanceof TimeValue){
			betweenVal = new Document(column.getColumnName(), 
					new Document("$gte", ((TimeValue)startExpr).getValue())
					.append("$lte", ((TimeValue)endExpr).getValue()));
		}else if(startExpr instanceof TimestampValue){
			betweenVal = new Document(column.getColumnName(), 
					new Document("$gte", ((TimestampValue)startExpr).getValue())
					.append("$lte", ((TimestampValue)endExpr).getValue()));
		}
		return betweenVal;
	}
	
	public static Document buildCompareCondition(String name, String condition, Expression expr){
		Document cond = null;
		if(expr instanceof LongValue){
			cond = new Document(name, 
					new Document(condition, ((LongValue)expr).getBigIntegerValue()));
		} else if(expr instanceof DoubleValue){
			cond = new Document(name, 
					new Document(condition, ((DoubleValue)expr).getValue()));
		}else if(expr instanceof StringValue){
			cond = new Document(name, 
					new Document(condition, ((StringValue)expr).getValue()));
		}else if(expr instanceof DateValue){
			cond = new Document(name, 
					new Document(condition, ((DateValue)expr).getValue()));
		}else if(expr instanceof TimeValue){
			cond = new Document(name, 
					new Document(condition, ((TimeValue)expr).getValue()));
		}else if(expr instanceof TimestampValue){
			cond = new Document(name, 
					new Document(condition, ((TimestampValue)expr).getValue()));
		}
		return cond;
	}
	
	public static Document parseWhereStament(Expression expr){
		Document query = new Document();
		if(expr instanceof AndExpression){
			AndExpression andExpression = (AndExpression)expr;
			Document left = parseWhereStament(andExpression.getLeftExpression());
			Document right = parseWhereStament(andExpression.getRightExpression());
			query.append("$and", Arrays.asList(left, right));
		} else if(expr instanceof OrExpression){
			OrExpression orExpression = (OrExpression)expr;
			Document left = parseWhereStament(orExpression.getLeftExpression());
			Document right = parseWhereStament(orExpression.getRightExpression());
			query.append("$or", Arrays.asList(left, right));
		} else if(expr instanceof Between){
			Between betweenExpr = (Between)expr;
			query = buildBetWeenCondition(betweenExpr); 
		} else if(expr instanceof EqualsTo){
			EqualsTo equalsTo = (EqualsTo)expr;
			boolean leftIsColumn = equalsTo.getLeftExpression() instanceof Column;
			Column column = leftIsColumn?(Column)(equalsTo.getLeftExpression()) : (Column)(equalsTo.getRightExpression());
			Expression valExpr = leftIsColumn? equalsTo.getRightExpression() : equalsTo.getLeftExpression();
			query = buildCompareCondition(column.getColumnName(), "$eq", valExpr);
		} else if(expr instanceof ExistsExpression){
		} else if(expr instanceof GreaterThan){
			GreaterThan greaterThan = (GreaterThan)expr;
			boolean leftIsColumn = greaterThan.getLeftExpression() instanceof Column;
			Column column = leftIsColumn?(Column)(greaterThan.getLeftExpression()) : (Column)(greaterThan.getRightExpression());
			Expression valExpr = leftIsColumn?greaterThan.getRightExpression() : greaterThan.getLeftExpression();
			query = buildCompareCondition(column.getColumnName(), "$gt", valExpr);
		} else if(expr instanceof GreaterThanEquals){
			GreaterThanEquals greaterThanEquals = (GreaterThanEquals)expr;
			boolean leftIsColumn = greaterThanEquals.getLeftExpression() instanceof Column;
			Column column = leftIsColumn?(Column)(greaterThanEquals.getLeftExpression()) : (Column)(greaterThanEquals.getRightExpression());
			Expression valExpr = leftIsColumn? greaterThanEquals.getRightExpression() : greaterThanEquals.getLeftExpression();
			query = buildCompareCondition(column.getColumnName(), "$gte", valExpr);
		} else if(expr instanceof InExpression){
		} else if(expr instanceof IsNullExpression){
		} else if(expr instanceof LikeExpression){
		} else if(expr instanceof MinorThan){
			MinorThan minorThan = (MinorThan)expr;
			boolean leftIsColumn = minorThan.getLeftExpression() instanceof Column;
			Column column = leftIsColumn?(Column)(minorThan.getLeftExpression()) : (Column)(minorThan.getRightExpression());
			Expression valExpr = leftIsColumn? minorThan.getRightExpression() : minorThan.getLeftExpression();
			query = buildCompareCondition(column.getColumnName(), "$lt", valExpr);
		} else if(expr instanceof MinorThanEquals){
			MinorThanEquals minorThanEquals = (MinorThanEquals)expr;
			boolean leftIsColumn = minorThanEquals.getLeftExpression() instanceof Column;
			Column column = leftIsColumn?(Column)(minorThanEquals.getLeftExpression()) : (Column)(minorThanEquals.getRightExpression());
			Expression valExpr = leftIsColumn? minorThanEquals.getRightExpression() : minorThanEquals.getLeftExpression();
			query = buildCompareCondition(column.getColumnName(), "$lte", valExpr);
		} else if(expr instanceof NotEqualsTo){
			NotEqualsTo notEqualsTo = (NotEqualsTo)expr;
			boolean leftIsColumn = notEqualsTo.getLeftExpression() instanceof Column;
			Column column = leftIsColumn?(Column)(notEqualsTo.getLeftExpression()) : (Column)(notEqualsTo.getRightExpression());
			Expression valExpr = leftIsColumn? notEqualsTo.getRightExpression() : notEqualsTo.getLeftExpression();
			query = buildCompareCondition(column.getColumnName(), "$ne", valExpr);
		}
		return query;
	}
	
	public static void addNameValueToDoc(Document doc, String name, Expression expr){
		if(expr instanceof LongValue){
			doc.append(name, ((LongValue)expr).getBigIntegerValue());
		} else if(expr instanceof DoubleValue){
			doc.append(name, ((DoubleValue)expr).getValue());
		}else if(expr instanceof StringValue){
			doc.append(name, ((StringValue)expr).getValue());
		}else if(expr instanceof DateValue){
			doc.append(name, ((DateValue)expr).getValue());
		}else if(expr instanceof TimeValue){
			doc.append(name, ((TimeValue)expr).getValue());
		}else if(expr instanceof TimestampValue){
			doc.append(name, ((TimestampValue)expr).getValue());
		}
	}
	
	
}

测试代码:

    
	public static void main(String[] args) throws SQLException {
		try {
			Class.forName("myjdbc.mongodb.MongoDBDriver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		Connection conn = DriverManager.getConnection("jdbc:mongo://127.0.0.1:27017/test", "", "");
		java.sql.Statement statement = conn.createStatement();
		statement.executeUpdate("insert into test01 (c1,c2,c3) values ('123','456','789')");
		statement.executeUpdate("update test01 set c2='ABC' where c1='123'");
		ResultSet rs = statement.executeQuery("select * from test01");
		while(rs.next()){
			System.out.println(String.format("%s %s %s", rs.getString(1), rs.getString(2), rs.getString(3)));
		}
		rs.close();
		rs = null;
		statement.executeUpdate("delete from test01");
	}

结果:

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值