`
javaso
  • 浏览: 51830 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

让程序帮我们生成常用的增删改查语句

    博客分类:
  • java
阅读更多

      无论用什么用什么orm工具,总有难免需要自己写sql语句的时候。用hibernate用多了,多多少少会怀念用jdbc的年代,因为可以自己写sql,再也不用去想什么n+1/延迟加载,缓存不一致问题了!

      但是当有一天你用jdbc/mybatis 开发,自己写sql的时候,也会怀念起hibernate,因为当你面对着一张表有N个字段,写个简简单简的增删改查的SQL语句,也要对着数据库表表结构,对着每个字段,小心翼翼地写着地来写SQL语句

     但是这对我来说,这不是问题,因为自己曾做过尝试,写过几个工具类帮我们生成   

     对于简单的SQL语句来讲,只要知道相关字段,表名,主键等,那剩下的工具就是拼字符串的问题了

    借助DatabaseMetaData  接口借供的API,可以获取到数据库表名,字段等相关信息。 主要由四个类完成相关功能。程序很简单,太勿忙就不写注悉了。下面直接上代码:

    

     table 主要用来存放相关table信息

public class TablesBean {

	private String primaryKey;

	private Map<String, String> columnMaps;

	private List<String> columns;

	private Class mapper;

	
	private String tableName;

	
	public Class getMapper() {
		return mapper;
	}

	
	public void setMapper(Class mapper) {
		this.mapper = mapper;
	}

	public String getPrimaryKey() {
		return primaryKey;
	}

	public void setPrimaryKey(String primaryKey) {
		this.primaryKey = primaryKey;
	}

	public String getTableName() {
		return tableName;
	}

	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	public Map<String, String> getColumnMaps() {
		return columnMaps;
	}

	public void setColumnMaps(Map<String, String> columnMaps) {
		this.columnMaps = columnMaps;
	}

	public List<String> getColumns() {
		if (columns.contains(primaryKey))
			columns.remove(primaryKey);
		
		return columns;
	}

	public void setColumns(List<String> columns) {
		this.columns = columns;
	}

	public boolean isPrimaryKey(String name) {

		return columns.contains(name);
	}

}

 

     用来存放相关所有tables信息

public class DatabaseBean {


	public DatabaseBean() {

	}

	private String databaseName;

	private Map<String, TablesBean> tables;



	public String getDatabaseName() {
		return databaseName;
	}

	public void setDatabaseName(String databaseName) {
		this.databaseName = databaseName;
	}

	public Map<String, TablesBean> getTables() {
		return tables;
	}

	public void setTables(Map<String, TablesBean> tables) {
		this.tables = tables;
	}



	public List<String> getAllTables() {
		List<String> list = new ArrayList<String>();
		for (Map.Entry<String, TablesBean> entry : tables.entrySet()) {
			list.add(entry.getKey());
		}

		return list;
	}
}

 

   这个类是生成sql语句核心,获到数据库中所有表名,及相关的列名

public class DatabaseInfoService {

	private static Logger logger = LoggerFactory
			.getLogger(DatabaseInfoService.class);

	private DatabaseBean databaseBean;


	private DatabaseMetaData dataMetaData;

	private Connection con;

	

	public DatabaseInfoService(Connection con) {

		this.con = con;
		try {
			this.init();
		} catch (Exception e) {
			logger.error("初始化数据失效:"+e.getMessage());
		} 
	}

	

	private void init() throws Exception {

		List<String> tables = this.getTables(con,null);
		databaseBean = this.getDatabaseBean();
		Map<String, TablesBean> tablesMap = new HashMap<String, TablesBean>();
		for (String table : tables) {
			Map<String, String> primaryKeys = this.getPrimaryKeys(con,table);
			TablesBean tablesBean = new TablesBean();
			List<String> columns = this.getColumns(con,table);
			tablesBean.setColumns(columns);
			if (primaryKeys.containsKey(table)) {
				tablesBean.setPrimaryKey(primaryKeys.get(table));
			}
			tablesBean.setTableName(table);
			tablesMap.put(table, tablesBean);
			databaseBean.setTables(tablesMap);
		}

	}

	public List<String> getColumns(Connection con,String tableName) throws Exception {
		DatabaseMetaData metaData = this.getDataMetaData(con);
		ResultSet rs = metaData.getColumns(null, null, tableName, null);
		List<String> columns = new ArrayList<String>();
		String columnName;
		while (rs.next()) {

			columnName = rs.getString("COLUMN_NAME");
			// System.out.println("列名:" + columnName);
			columns.add(columnName);
		}

		return columns;
	}

	public Map<String, String> getPrimaryKeys(Connection con,String table) throws Exception {
		Map<String, String> map = new HashMap<String, String>();
		DatabaseMetaData metaData = this.getDataMetaData(con);
		ResultSet rs = metaData.getPrimaryKeys(null, null, table);
		String tableName;
		String column;
		while (rs.next()) {
			tableName = rs.getString("TABLE_NAME");
			column = rs.getString("COLUMN_NAME");
			// System.out.println("表名为:" + tableName + "主键:" + column);
			map.put(tableName, column);
		}

		return map;
	}

	public List<String> getTables(Connection con,String tableName) throws Exception {
		DatabaseMetaData metaData = this.getDataMetaData(con);
		ResultSet rs = metaData.getTables(null, null, tableName, null);
		String rtableName;
		List<String> tables = new ArrayList<String>();
		while (rs.next()) {
			rtableName = rs.getString("TABLE_NAME");
			// System.out.println("表名:" + rtableName);
			tables.add(rtableName);

		}

		return tables;

	}

	public DatabaseMetaData getDataMetaData(Connection con) {
		if (dataMetaData != null)
			return dataMetaData;
        
		if(con ==null)
		 throw new NullPointerException("数据库连接不能为空");
			
		try {
			dataMetaData = con.getMetaData();
		} catch (SQLException e) {
			logger.error("获取metadata出错:" + e.getMessage());
		}
		return dataMetaData;
	}




	public DatabaseBean getDatabaseBean() {

		return databaseBean != null ? databaseBean : new DatabaseBean();
	}

}

 

      供外部程序调用生成sql的类:

    

public class SqlAutoCreator {

	//用线程安全map可以不进行同步
	private ConcurrentMap<String, DatabaseBean> container;

	private static final String CONTAINER_NAME = "DATABASE_INFO";

	private static Logger logger = LoggerFactory
			.getLogger(SqlAutoCreator.class);

	private Connection connection;

	private boolean hasColumnLable = false;

	private boolean hasNamedParam = false;

	public SqlAutoCreator(Connection con) {
		try {
			this.connection = con;
			this.initContainer(con);//仅初始化一次,减少相关资源消耗
		} finally {
			closeDB(con);
		}
	}

	public SqlAutoCreator() {
		try {
			this.initContainer(connection);
		} finally {
			closeDB(connection);
		}
	}

	public String createQuerySql(String table) {
		TablesBean tablebean = this.getTablesBean(table);
		if (tablebean == null)
			return null;

		StringBuffer sb = new StringBuffer();
		List<String> columns = tablebean.getColumns();
		sb.append("SELECT ");
		for (String column : columns) {
			sb.append(column).append(",");
		}
		sb.deleteCharAt(sb.length() - 1);
		sb.append("  FROM ").append(tablebean.getTableName());
		sb.append(" WHERE ").append(tablebean.getPrimaryKey()).append(" = ");

		if (hasNamedParam) {//可以设置是否开启命名参数,默认是false
			sb.append(":").append(tablebean.getPrimaryKey());
		} else {
			sb.append("?");
		}
		return sb.toString();
	}

	public String createInsertSQL(String table) {
		TablesBean tablebean = this.getTablesBean(table);
		if (tablebean == null)
			return null;
		List<String> columns = tablebean.getColumns();
		StringBuilder sb = new StringBuilder();
		sb.append("INSERT INTO ").append(tablebean.getTableName() + "(");
		for (String column : columns) {
			sb.append(column);
			sb.append(",");
		}
		sb.deleteCharAt(sb.length() - 1);
		sb.append(")");
		sb.append(" VALUES(");

		for (String column : columns) {
			if (hasNamedParam) {
				sb.append(":");
				sb.append(column);
			} else {
				sb.append("?");
			}
			sb.append(",");
		}
		sb.deleteCharAt(sb.length() - 1);
		sb.append(")");
		return sb.toString();
	}

	public String createUpdateSQL(String table) {
		TablesBean tablebean = this.getTablesBean(table);
		if (tablebean == null)
			return null;
		List<String> columns = tablebean.getColumns();
		StringBuilder sb = new StringBuilder();

		sb.append("UPDATE ");
		sb.append(tablebean.getTableName());
		sb.append(" SET ");
		for (String column : columns) {
			sb.append(column);
			if (hasNamedParam) {
				sb.append("=:");
				sb.append(column);
			} else {
				sb.append("=?");
			}
			sb.append(",");
		}
		sb.deleteCharAt(sb.length() - 1);
		sb.append(" WHERE ");
		sb.append(tablebean.getPrimaryKey());
		sb.append("=");
		if (hasNamedParam) {
			sb.append(":");
			sb.append(tablebean.getPrimaryKey());
		} else {
			sb.append("?");
		}
		return sb.toString();
	}

	public String createDeleteSQL(String table) {
		TablesBean tablebean = this.getTablesBean(table);
		if (tablebean == null)
			return null;
		// List<String> columns = tablebean.getColumns();
		StringBuilder sb = new StringBuilder();
		sb.append("DELETE FROM ").append(tablebean.getTableName()).append(
				" WHERE ").append(tablebean.getPrimaryKey()).append("=");
		if (hasNamedParam) {
			sb.append(":");
			sb.append(tablebean.getPrimaryKey());
		} else {
			sb.append("?");
		}
		return sb.toString();
	}

	public List<String> createAllQuerySQL() {
		List<String> allQuerySQL = new ArrayList<String>();
		List<String> tables = this.getAllTables();
		for (String table : tables) {
			allQuerySQL.add(this.createQuerySql(table));
		}
		return allQuerySQL;
	}

	public List<String> createAllInsertSQL() {
		List<String> list = new ArrayList<String>();
		List<String> tables = this.getAllTables();
		for (String table : tables) {
			list.add(this.createInsertSQL(table));
		}
		return list;
	}

	public List<String> createAllUpdateSQL() {
		List<String> list = new ArrayList<String>();
		List<String> tables = this.getAllTables();
		for (String table : tables) {
			list.add(this.createUpdateSQL(table));
		}
		return list;
	}

	public List<String> createAllDeleteSQL() {
		List<String> list = new ArrayList<String>();
		List<String> tables = this.getAllTables();
		for (String table : tables) {
			list.add(this.createDeleteSQL(table));

		}
		return list;
	}

	protected void initContainer(Connection con) {
		container = new ConcurrentHashMap<String, DatabaseBean>();
		DatabaseInfoService databaseService = new DatabaseInfoService(con);
		DatabaseBean databaseBean = databaseService.getDatabaseBean();
		container.put(CONTAINER_NAME, databaseBean);
	}

	public List<String> getAllTables() {
		return this.getDatabaseInfo().getAllTables();
	}

	private TablesBean getTablesBean(String table) {
		DatabaseBean databaseinfo = getDatabaseInfo();
		Map<String, TablesBean> tables = databaseinfo.getTables();
		TablesBean tablebean = tables.get(table);
		return tablebean;

	}

	public DatabaseBean getDatabaseInfo() {
		return container.get(CONTAINER_NAME);

	}

	public void setConnection(Connection connection) {
		this.connection = connection;
	}

	public boolean isHasColumnLable() {
		return hasColumnLable;
	}

	public void setHasColumnLable(boolean hasColumnLable) {
		this.hasColumnLable = hasColumnLable;
	}

	public boolean isHasNamedParam() {
		return hasNamedParam;
	}

	public void setHasNamedParam(boolean hasNamedParam) {
		this.hasNamedParam = hasNamedParam;
	}

	protected void closeDB(Connection con) {
		try {
			con.close();
		} catch (SQLException e) {

			logger.warn("关闭数据库连接异常:" + e.getMessage());
		}
	}
}

 

  调用:

 

@ContextConfiguration(locations = "/applicationContext.xml")
public class ConnectionSourceTest extends AbstractJUnit4SpringContextTests {

	@Resource
	DataSource dataSource;

	
	@Test
	public void testGetQuerySQL()throws Exception{
		SqlAutoCreator creator = new SqlAutoCreator(dataSource.getConnection());
		
	    String sql=	creator.createQuerySql("t_userinfo");
		System.out.println("查找SQL语句:"+sql);
	}
	
	@Test
	public void testGetInsertSQL()throws Exception{
		SqlAutoCreator creator = new SqlAutoCreator(dataSource.getConnection());
		creator.setHasNamedParam(false);
	    String sql=	creator.createInsertSQL("t_userinfo");
		System.out.println("插入SQL语句:"+sql);
	   
	}
	@Test
	public void getDeleteSQL() throws Exception{
		SqlAutoCreator creator = new SqlAutoCreator(dataSource.getConnection());
		
	    String sql=	creator.createDeleteSQL("t_userinfo");
		System.out.println("删除SQL语句:"+sql);
	   
	}
	@Test
	public void getUpdateSQL() throws Exception{
		SqlAutoCreator creator = new SqlAutoCreator(dataSource.getConnection());
		
	    String sql=	creator.createUpdateSQL("t_userinfo");
		System.out.println("删除SQL语句:"+sql);
	   
	}
	@Test
	public void testGetAllSql() throws Exception{
		SqlAutoCreator creator = new SqlAutoCreator(dataSource.getConnection());
		creator.setHasNamedParam(true);
		System.out.println("删除:"+creator.createAllDeleteSQL());
		System.out.println("插入:"+creator.createAllInsertSQL());
		System.out.println("查找:"+creator.createAllQuerySQL());
		System.out.println("更新:"+creator.createAllUpdateSQL());
	}
	

	
}

 

    由针MyBatis或者spring jdbc  sql文件以放在外部文件,我们其实可以利用模板技术(freemarker velocity)生成所需要的文件,当然这是后话了。

   

 

  PS: 以上程序在mysql数据库测试通过,其它数据库未做测试,如有bug欢迎指出

   

 

1
3
分享到:
评论
2 楼 recole 2012-05-13  
我也有写一个生成基本sql操作的工具,当然我的是.net版的。对于自由select的结果集,.net可以返回DataTable,不知java有没有类似的?
1 楼 shuang245 2011-09-24  
非常好,顶顶顶!

相关推荐

    php增删改查

    用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执行编译后代码,编译可以达到加密和优化代码...

    可以自动生成sql语句的工具

    可以自动生成sql语句的工具。可以生成formbean及增删改查等基本代码。参数输入表名称即可。

    mybatis-base增删改查分页批量操作简单动态sql调用存储过程.zip

    标签是Mabits动态SQL中最常用的一个标签之一,它的作用是根据给定条件包含或排除不同的部分,以生成不同的SQL语句。在XML文件中,标签通常被嵌套在其他标签内,如、和等标签内,用于控制生成的SQL语句的结构和内容。...

    java-利用GUI实现窗口学生管理系统(jdbc连接数据库-MySQL)

    增删改查语句在数据库中运行成功 3).可以使用Statement语句或PreparedStatement语句 4).主函数,用于选择下一步要执行的操作 5).连接方法,连接数据库的4个属性 6).关闭连接 方法,断开数据库连接

    自动生成entity和dao层

    java源码有备注说明自动生成java entity和dao层,包含动态的sql语句,增删改查都有,为程序猿专注主要业务逻辑。

    通过MyBatis动态SQL完成数据库表的增、删、改、查、模糊查询..zip

    标签是Mabits动态SQL中最常用的一个标签之一,它的作用是根据给定条件包含或排除不同的部分,以生成不同的SQL语句。在XML文件中,标签通常被嵌套在其他标签内,如、和等标签内,用于控制生成的SQL语句的结构和内容。...

    ORM及代码生成器C#源码(2012最新版Kenly.DBFramework4.6.5.5)

    4、根据ID、主键或自定义条件对数据表进行增、删、改操作。 5、实现一对一、一对多、多对一和多对多的关系映射。 6、支持单个对象和多个对象之间的事务控制。 7、支持查询结果排序。 8、支持查询表达式生成。 9...

    .net2.0版代码生成器

    会自动生成SQL语句,存储过程,资源文件及增删改查页面。 一个代码生成器,后面要跟着一个整体框架,这样生成的代码才有地方可放。我的整体框架会在以后一步步提供。框架设计的好,生成的代码才会更少,更易理解,...

    控制台程序【泛型+反射】

    作业内容是做一个控制台程序: 1 建立一个数据库,然后执行下面的数据库脚本,会增加两张表 User Company,大家可以去表里面自己多...8 进阶需求(可选):每个实体类的基础增删改查SQL语句是不变的,用泛型缓存试试!

    LTP.Net代码自动生成器(DbToCode)

    可以根据选定的数据库和表(可多选),生成表的创建脚本,以及表数据的插入脚本,同时可以生成表的增,删,改,查等操作的存储过程脚本。支持在当前生成和导出脚本文件功能. 5. 自动生成数据库结构文档。 可以根据...

    SqlTransfer.rar

    字段生成new SqlParameter,cmdParms等代码,不用自己一个一个拼insert和update的字段,极大方便了程序进数据表增删改查操作。贴上VALUES下面的语句后,先点下初始化按钮再点其它功能按钮

    BeetlSQL数据库访问框架 (DAO工具).rar

    无需注解,自动生成大量内置SQL,轻易完成增删改查功能 支持跨数据库平台,开发者所需工作减少到最小 具备Interceptor功能,可以调试,性能诊断SQL,以及扩展其他功能 内置支持主从数据库,通过扩展,可以支持更复杂...

    动软.Net代码自动生成器(Codematic)

    可以根据选定的数据库和表(可多选),生成表的创建脚本,以及表数据的插入脚本,同时可以生成表的增,删,改,查等操作的存储过程脚本。支持在当前生成和导出脚本文件功能. &lt;br/&gt;5. 自动生成数据库结构文档...

    nodejs基于微信小程序的书籍销售系统的实现.rar

    数据库: 使用MySQL数据库进行数据存储,包括图书信息、用户信息、订单信息等,通过SQL语句进行数据的增删改查操作。 开发工具: 使用IntelliJ IDEA、Eclipse等集成开发环境进行项目开发和调试,使用Maven进行依赖...

    图书管理系统(struts+hibernate+spring)130225.rar

    该系统旨在提供一个简洁高效的图书管理解决方案,允许用户进行图书的增删改查操作,同时支持借阅和归还流程的管理。借助于Struts的Action类和Form Bean,用户界面与后端逻辑得以有效分离,使得功能扩展和维护更为...

    MYSQL常用命令大全

    现在我们结束操作并退出MySQL客户程序:  mysql&gt; exit  Bye9! 1:使用SHOW语句找出在服务器上当前存在什么数据库: mysql&gt; SHOW DATABASES; 2:2、创建一个数据库MYSQLDATA mysql&gt; Create DATABASE MYSQLDATA; 3:...

    springmybatis

    mybatis实战教程mybatis in action之三实现数据的增删改查 mybatis实战教程mybatis in action之四实现关联数据的查询 mybatis实战教程mybatis in action之五与spring3集成附源码 mybatis实战教程mybatis in action之...

    PDF.NET 数据开发框架V3.0源码

    * 只需要一行代码实现页面数据的增,删,改,查。 * 基于SQL词法分析的支持多种数据库的高效分页类,你只需要设置SQL语句和分页属性它便能够为你生成特定数据库平台的当前页数据的SQL语句。 * 一套实用工具,可以...

    AppFramework数据库访问组件_代码生成插件_V1.1.rar

    除了实现数据的增删改查,数据访问层还要提供一些与业务无关功能,例如面向对象的持久化与访问机制、本地事务与分布式事务支持、多数据库支持,这些机制或功能形成相对独立的逻辑领域,其主要目的有: &lt;br&gt;1、 ...

    PDF.NET数据开发框架V3.0演示版

    * 只需要一行代码实现页面数据的增,删,改,查。 * 基于SQL词法分析的支持多种数据库的高效分页类,你只需要设置SQL语句和分页属性它便能够为你生成特定数据库平台的当前页数据的SQL语句。 * 一套实用工具,可以...

Global site tag (gtag.js) - Google Analytics