• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

codefinger-dao: Java数据库访问工具

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

codefinger-dao

开源软件地址:

https://gitee.com/codefinger/codefinger-dao

开源软件介绍:

#codefinger-dao

#简介

数据库访问工具,功能强大、简洁、高效、零配置,支持MySQL、SQLServer、Oracle。

#特性(完整Demo,请看org.codefinger.test.DaoUtilDemo)

###1.语法分析,智能展开、拼接SQL语句

// 前面这里采用阿里巴巴的数据库连接池,主要是为了演示执行的SQL语句(您可以采用其它数据连接池)DruidDataSource dataSource = new DruidDataSource();Log4jFilter log4jFilter = new Log4jFilter();log4jFilter.setResultSetLogEnabled(false);log4jFilter.setStatementLogEnabled(false);log4jFilter.setStatementExecutableSqlLogEnable(true);Filter filter = log4jFilter;dataSource.setProxyFilters(Arrays.asList(filter));// 这里采用MySQL进行演示,您也可以选择SQLServer或OracledataSource.setUrl("jdbc:mysql://192.168.189.135:3306/codefinger?useUnicode=true&characterEncoding=utf-8");dataSource.setUsername("root");dataSource.setPassword("root");// 1.这里是真正开始,创建数据库工具DaoUtil daoUtil = new DaoUtil();daoUtil.setDataSource(dataSource);// 2.然后您就可以创建查询对象了Query query = daoUtil.createQuery("select * from customer where f_name left like :name and f_age > :age");// 3.进行查询query.putParam("name", "张三").getMapList();/* * 这时,工具自动进行了如下查询(只用了其中一个查询条件): *  * SELECT  * 		CUSTOMER.F_ID,  * 		CUSTOMER.F_NAME,  * 		CUSTOMER.F_AGE, * 		CUSTOMER.F_MONEY  * FROM  * 		CUSTOMER  * WHERE  * 		F_NAME LIKE '张三%' */query.putParam("age", 15).getMapList();/* * 这时,工具自动进行了如下查询(这次用了另一个查询条件): *  * SELECT  * 		CUSTOMER.F_ID,  * 		CUSTOMER.F_NAME,  * 		CUSTOMER.F_AGE, * 		CUSTOMER.F_MONEY  * FROM  * 		CUSTOMER  * WHERE  * 		F_AGE > 15 */query.putParam("name", "张三").putParam("age", 15).getMapList();/* * 这时,工具自动进行了如下查询(这次两个查询条件都同时利用了): *  * SELECT  * 		CUSTOMER.F_ID,  * 		CUSTOMER.F_NAME,  * 		CUSTOMER.F_AGE, * 		CUSTOMER.F_MONEY  * FROM  * 		CUSTOMER  * WHERE  * 		F_NAME LIKE '张三%'  * 		AND F_AGE > 15 */// 4.您可以试试更复杂的查询条件query = daoUtil.createQuery("select * from customer where f_name left like :name and (f_age >= :minAge or f_age <= :maxAge) order by f_age,f_name desc");query.putParam("minAge", 15)// 只根据最小年龄进行筛选		.setOrders(0)// 只根据年龄进行排序		.getMapList();/* * 这时,工具自动进行了如下查询(是不是很智能): *  * SELECT  * 		CUSTOMER.F_ID,  * 		CUSTOMER.F_NAME,  * 		CUSTOMER.F_AGE, * 		CUSTOMER.F_MONEY  * FROM  * 		CUSTOMER  * WHERE  * 		F_AGE >= 15  * ORDER BY  * 		F_AGE ASC */

###2.支持命名参数和顺序参数

// 刚才上面的掩饰采用的就是命名参数,这里采用顺序参数query = daoUtil.createQuery("select * from customer where f_name all like ? and (f_age >= ? or f_age <= ?) order by f_age,f_name desc");query.setParams("张三", null, 20)// 只根据姓名和最大年龄进行筛选		.setOrders(1)// 只根据姓名进行排序		.getMapList();/* * 这时,工具自动进行了如下查询(真的很智能!): *  * SELECT  * 		CUSTOMER.F_ID,  * 		CUSTOMER.F_NAME,  * 		CUSTOMER.F_AGE, * 		CUSTOMER.F_MONEY  * FROM  * 		CUSTOMER  * WHERE  * 		F_NAME LIKE '%张三%'  * 		AND F_AGE <= 20  * ORDER BY  * 		F_NAME DESC */

###3.支持复杂的查询(左、内连接查询、子查询、Union、各种条件表达式like、in、exists、any、all等)

// @formatter:off// 刚才上面的SQL语句还是太简单了,来点复杂的看看query = daoUtil.createQuery(		"select " + 				"A.f_id id," + 				"B.f_name as name," + 				"C.f_age age," + 				"D.f_money as money " + 		"from " + 				"customer A " + 				"inner join customer B on B.f_id = A.f_id " + 				"left join customer C on C.f_id = B.f_id " + 				"inner join customer D on D.f_id = C.f_id " + 		"where " + 				"(A.f_age >= :minAge or A.f_age <= :minAge) " + 				"and B.f_name left like :leftName " + 				"and C.f_name all like :allName " + 				"and D.f_money not in (3.5,3.6,:moneyNotIn) " + 				"and D.f_age is not null " + 				"and D.f_age = (select f_age from customer where f_age != :notAge) " + 		"group by " + 				"A.*,B.*,C.*,D.* " + 		"having " + 				"AVG(D.f_money) > 1000 " + 		"union all " + 				"select " + 					"f_id id," + 					"f_name name," + 					"f_age as age," + 					"f_money money " + 				"from customer " + 		"order by " + 				"money desc,age asc");// @formatter:onquery.putParam("notAge", 25) // 年龄不等于25		.putParam("moneyNotIn", Arrays.asList(3.7, 9.125, 10000.9)) // Money不包含列表中的值		.putParam("allName", "王") // 模糊查询,姓名中包含‘王’的		.putParam("minAge", 10)// 最小年龄		.setOrders(0) // 只按照Money排序		.getMapSet();/* * 就算是这么复杂的SQL语句,也能够被智能分析出来: *  * SELECT * 		A.F_ID AS ID, * 		B.F_NAME AS NAME,  * 		C.F_AGE AS AGE,  * 		D.F_MONEY AS MONEY  * FROM  * 		CUSTOMER A  * INNER JOIN CUSTOMER B ON B.F_ID = A.F_ID  * LEFT JOIN CUSTOMER C ON C.F_ID = B.F_ID  * INNER JOIN CUSTOMER D ON D.F_ID = C.F_ID  * WHERE  * 		(A.F_AGE >= 10 OR A.F_AGE <= 10)  * 		AND C.F_NAME LIKE '%王%' * 		AND D.F_MONEY NOT IN (3.5, 3.6, 3.7, 9.125, 10000.9)  * 		AND D.F_AGE IS NOT NULL  * 		AND D.F_AGE = (SELECT F_AGE FROM CUSTOMER WHERE F_AGE != 25) * GROUP BY  * 		A.F_ID, A.F_NAME, A.F_AGE, A.F_MONEY, B.F_ID, B.F_NAME, * 		B.F_AGE, B.F_MONEY, C.F_ID, C.F_NAME, C.F_AGE, C.F_MONEY, D.F_ID, * 		D.F_NAME, D.F_AGE, D.F_MONEY  * HAVING  * 		AVG(DISTINCT D.F_MONEY) > 1000 * UNION ALL  * 		SELECT  * 			F_ID AS ID, * 			F_NAME AS NAME,  * 			F_AGE AS AGE,  * 			F_MONEY AS MONEY  * 		FROM CUSTOMER  * ORDER BY  * 		MONEY DESC */

###4.支持总量(Count)和分页查询(总量查询能够查询出本次查询结果(不分页)的总记录数)

// 让我们看看查询Count和分页有多简单QueryChain queryChain = query.putParam("notAge", 25) // 年龄不等于25		.putParam("moneyNotIn", Arrays.asList(3.7, 9.125, 10000.9)) // Money不包含列表中的值		.putParam("allName", "王") // 模糊查询,姓名中包含‘王’的		.putParam("minAge", 10)// 最小年龄		.setOrders(0) // 只按照Money排序		.setPage(5, 10); // 查第5页,每页显示10条// Count查询queryChain.queryCount();/* * SELECT  * 		COUNT(1)  * FROM  * 	( * 		SELECT  * 			A.F_ID AS ID,  * 			B.F_NAME AS NAME,  * 			C.F_AGE AS AGE,  * 			D.F_MONEY AS MONEY  * 		FROM  * 			CUSTOMER A  * 		INNER JOIN CUSTOMER B ON B.F_ID = A.F_ID  * 		LEFT JOIN CUSTOMER C ON C.F_ID = B.F_ID  * 		INNER JOIN CUSTOMER D ON D.F_ID = C.F_ID  * 		WHERE  * 			(A.F_AGE >= 10 OR A.F_AGE <= 10)  * 			AND C.F_NAME LIKE '%王%' * 			AND D.F_MONEY NOT IN (3.5, 3.6, 3.7, 9.125, 10000.9)  * 			AND D.F_AGE IS NOT NULL  * 			AND D.F_AGE = (SELECT F_AGE FROM CUSTOMER WHERE F_AGE != 25) * 		GROUP BY  * 			A.F_ID, A.F_NAME, A.F_AGE, A.F_MONEY, B.F_ID, B.F_NAME, * 			B.F_AGE, B.F_MONEY, C.F_ID, C.F_NAME, C.F_AGE, C.F_MONEY, D.F_ID, * 			D.F_NAME, D.F_AGE, D.F_MONEY  * 		HAVING  * 			AVG(DISTINCT D.F_MONEY) > 1000 * 		UNION ALL  * 			SELECT  * 				F_ID AS ID, F_NAME AS NAME, F_AGE AS AGE, F_MONEY AS  MONEY  * 			FROM  * 				CUSTOMER * 	) ALL_CONTENT */// 分页查询queryChain.getMapList();/* * SELECT  * 		A.F_ID AS ID,  * 		B.F_NAME AS NAME,  * 		C.F_AGE AS AGE,  * 		D.F_MONEY AS MONEY  * FROM  * 		CUSTOMER A  * INNER JOIN CUSTOMER B ON B.F_ID = A.F_ID  * LEFT JOIN CUSTOMER C ON C.F_ID = B.F_ID  * INNER JOIN CUSTOMER D ON D.F_ID = C.F_ID  * WHERE  * 		(A.F_AGE >= 10 OR A.F_AGE <= 10)  * 		AND C.F_NAME LIKE '%王%' * 		AND D.F_MONEY NOT IN (3.5, 3.6, 3.7, 9.125, 10000.9)  * 		AND D.F_AGE IS NOT NULL  * 		AND D.F_AGE = (SELECT F_AGE FROM CUSTOMER WHERE F_AGE != 25) * GROUP BY  * 		A.F_ID, A.F_NAME, A.F_AGE, A.F_MONEY, B.F_ID, B.F_NAME, * 		B.F_AGE, B.F_MONEY, C.F_ID, C.F_NAME, C.F_AGE, C.F_MONEY, D.F_ID, * 		D.F_NAME, D.F_AGE, D.F_MONEY  * HAVING  * 		AVG(DISTINCT D.F_MONEY) > 1000 * UNION ALL  * 		SELECT  * 			F_ID AS ID, F_NAME AS NAME, F_AGE AS AGE, F_MONEY AS  MONEY  * 		FROM  * 			CUSTOMER  * ORDER BY  * 		MONEY DESC  * LIMIT 40, 10 */

###5.多样化的返回结果

// 除了上面用到过的getMapList,还有其它可选的返回值类型// 您可以返回List泛型queryChain.getList(Customer.class);// 当您确定返回值只有一行数据时,您可以返回Pojo类型queryChain.fetch(Customer.class);// 当您确定返回值只有一行一列的时候,您可以这样int avg = daoUtil.createQuery("select sum(f_age) ageSum from customer").getUnique(DaoType.INT);System.out.println(avg);// 如果说您想要自己封装返回值类型,您可以这样queryChain.getResult(new QueryCallback<List<Customer>>() {	@Override	public List<Customer> getResult(ResultSet resultSet, String[] names) throws SQLException {		List<Customer> customers = new ArrayList<Customer>();		PojoBuilder<Customer> builder = QueryUtil.getPojoBuilder(Customer.class, resultSet, names);		while (resultSet.next()) {			Customer customer = builder.nextPojo();			customer.setF_name("我想自己修改返回值");			customers.add(customer);		}		return customers;	}});

###6.这里几乎包含所有您需要用到的增删改操作

// 首先试试新增操作Customer customer = new Customer("张三", 19, 100);daoUtil.insert("customer", customer);System.out.println(customer.getF_id()); // 自动为Pojo对象生成了主键// 批量新增Customer[] customers = new Customer[] { //// 两个对象		new Customer("李四", 18, 100), //		new Customer("王五", 17, 99) //};daoUtil.insert("customer", customers);daoUtil.insert("customer", Arrays.asList(customers)); // 也可以使用集合// 也可以采用链式调用的方式做新增daoUtil.insertInto("customer").set("f_name = ?, f_age = 16,f_money = ?").execute("赵六", 105);daoUtil.insertInto("customer").set("f_name = :name, f_age = :age")//		.putParam("name", "田七")//		.putParam("age", 15)//		.execute();// 然后试试修改操作customer.setF_money(200);daoUtil.update("customer", customer);daoUtil.update("customer", Arrays.asList(customer, customer)); // 同样支持批量修改daoUtil.updateFrom("customer")//		.set("f_name = :newName, f_age = :newAge, f_money = 100")//		.where("f_id = :oldName and f_age > :oldAge")//		.putParam("newName", "新名字")//		.putParam("newAge", 20).putParam("oldName", "旧名字")//		.putParam("oldAge", 18)//		.execute();// 删除操作daoUtil.deleteByID("customer", 18); // 通过主键删除daoUtil.deleteByID("customer", 18, 19, 20); // 批量删除daoUtil.deleteFrom("customer").where("f_name left like ?").execute("张三");// 名称像“张三%”的将被删除daoUtil.deleteFrom("customer").execute();// 删除“customer”表的所有记录

#轻松与Spring进行集成

###Spring的设计的确是相当精妙,目前大多数项目都基于是Spring的容器来做的###Spring中提供了声明式事物、注解等等特性使得我们开发更加简单、容易###下面将演示如何在Spring中进行完美的集成(以下示例的所有源代码都在org.codefinger.test.spring包中能找到)

####首先是Spring的配置文件

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 	xmlns:tx="http://www.springframework.org/schema/tx"	xmlns:context="http://www.springframework.org/schema/context"	xmlns:aop="http://www.springframework.org/schema/aop"	xsi:schemaLocation="http://www.springframework.org/schema/beans 						http://www.springframework.org/schema/beans/spring-beans.xsd 						http://www.springframework.org/schema/tx 						http://www.springframework.org/schema/tx/spring-tx.xsd 						http://www.springframework.org/schema/context              				http://www.springframework.org/schema/context/spring-context.xsd           				http://www.springframework.org/schema/aop           				http://www.springframework.org/schema/aop/spring-aop.xsd">	<!-- 阿里巴巴数据库连接池的SQL日志配置 -->	<bean id="log-filter" class="com.alibaba.druid.filter.logging.Log4jFilter">		<property name="resultSetLogEnabled" value="false" />		<property name="statementExecutableSqlLogEnable" value="true" />		<property name="statementLogEnabled" value="false" />	</bean>	<!-- 配置一下阿里巴巴的数据连接池,您可以采用其它的数据库连接池 -->	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"		init-method="init" destroy-method="close">		<!-- <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"></property> -->		<!-- <property name="url" value="jdbc:sqlserver://127.0.0.1:1433;databaseName=dcode"></property> -->		<property name="url"			value="jdbc:mysql://192.168.189.135:3306/codefinger?useUnicode=true&amp;&amp;characterEncoding=utf-8"></property>		<property name="username" value="root"></property>		<property name="password" value="root"></property>		<property name="proxyFilters">			<list>				<ref bean="log-filter" />			</list>		</property>		<!-- 配置初始化大小、最小、最大 -->		<property name="initialSize" value="1" />		<property name="minIdle" value="1" />		<property name="maxActive" value="20" />		<!-- 配置获取连接等待超时的时间 -->		<property name="maxWait" value="60000" />		<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->		<property name="timeBetweenEvictionRunsMillis" value="60000" />		<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->		<property name="minEvictableIdleTimeMillis" value="300000" />		<property name="testWhileIdle" value="true" />		<property name="testOnBorrow" value="false" />		<property name="testOnReturn" value="false" />		<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->		<property name="poolPreparedStatements" value="true" />		<property name="maxPoolPreparedStatementPerConnectionSize"			value="20" />		<!-- 配置监控统计拦截的filters -->		<!-- <property name="filters" value="stat" /> -->	</bean>	<!-- 事物管理对象 -->	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">		<property name="dataSource" ref="dataSource"></property>	</bean>	<!-- 数据源代理对象 -->	<bean id="transactionAwareDataSourceProxy" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">		<property name="targetDataSource" ref="dataSource"></property>	</bean>	<!-- 这样您就可以使用注解式的事物 -->	<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />	<!-- 这是声明式事物配置,配置事务传播特性 -->	<tx:advice id="TestAdvice" transaction-manager="transactionManager">		<tx:attributes>			<tx:method name="save*" propagation="REQUIRED" />			<tx:method name="del*" propagation="REQUIRED" />			<tx:method name="update*" propagation="REQUIRED" />			<tx:method name="add*" propagation="REQUIRED" />			<tx:method name="find*" propagation="REQUIRED" />			<tx:method name="get*" propagation="REQUIRED" />			<tx:method name="apply*" propagation="REQUIRED" />		</tx:attributes>	</tx:advice>	<!-- 配置参与事务的类 -->	<aop:config>		<aop:pointcut id="allTestServiceMethod" expression="execution(* org.codefinger.test.spring.*.*(..))" />		<aop:advisor pointcut-ref="allTestServiceMethod" advice-ref="TestAdvice" />	</aop:config>	<!-- 数据库工具配置 -->	<bean id="daoUtil" class="org.codefinger.dao.DaoUtil">		<!-- 如需事物生效,必须使用Spring的DataSource代理才行(网上好多教程中的事物没配置代理,其实根本就不生效) -->		<property name="dataSource" ref="transactionAwareDataSourceProxy"></property>	</bean>	<!-- 这时,您可以将复杂的查询配置在Spring的配置文件中(您也可以将SQL配置到单独的Spring配置文件中,然后import进来,这是不是像MyBatis) -->	<bean id="queryCustomer" class="org.codefinger.dao.SpringQuery">		<property name="sql">			<value>				<![CDATA[					select						A.f_id id,						B.f_name as name,						C.f_age age,						D.f_money as money					from  						customer A  						inner join customer B on B.f_id = A.f_id  						left join customer C on C.f_id = B.f_id  						inner join customer D on D.f_id = C.f_id  					where  							(A.f_age >= :minAge or A.f_age <= :minAge)  							and B.f_name left like :leftName  							and C.f_name all like :allName  							and D.f_money not in (3.5,3.6,:moneyNotIn)  							and D.f_age is not null  							and D.f_age = (select f_age from customer where f_age != :notAge)  					group by  							A.*,B.*,C.*,D.*  					having  							AVG(D.f_money) > 1000  					union all  							select  								f_id id, 								f_name name, 								f_age as age, 								f_money money  							from 								customer  					order by  							money desc,age asc				]]>			</value>		</property>	</bean>	<!-- 让Spring扫描我们的控制层 -->	<context:component-scan base-package="org.codefinger.test.spring" /></beans>

####然后我们可以写个Service试试

package org.codefinger.test.spring;import java.util.List;import java.util.Map;import org.codefinger.dao.DaoUtil;import org.codefinger.dao.Query;import org.codefinger.test.Customer;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Service;/*** * <p> * 您可以把{@link MyService}当作为您项目中Action、Controller、Service等等<br/> * </p> *  * @author jack * */@Servicepublic class MyService {	/**	 * 从Spring获取配置好的SQL	 */	@Autowired	@Qualifier("queryCustomer")	private Query	queryCustomer;	/**	 * 自动注入数据库工具	 */	@Autowired	private DaoUtil	daoUtil;	/**	 * 根据最小年龄和名称做模糊查询	 * 	 * @param minAge	 * @param allName	 * @return	 */	public List<Map<String, Object>> getMapList(int minAge, String allName) {		return queryCustomer.putParam("minAge", minAge).putParam("allName", allName).getMapList();	}	/**	 * 添加	 * 	 * @param customer	 * @return	 */	public boolean add(Customer customer) {		return daoUtil.insert("customer", customer);	}	/**	 * 修改	 * 	 * @param customer	 * @return	 */	public boolean update(Customer customer) {		return daoUtil.update("customer", customer);	}	/*	 * 当然,您还能用它做更多的数据访问工作(复杂的修改、删除、分页等等),这就又您自由发挥了......	 */}

####最后看看成果

package org.codefinger.test.spring;import org.codefinger.test.Customer;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class SpringDemo {	@SuppressWarnings("resource")	public static void main(String[] args) {		// 这里做演示,手动加载Spring文件(实际项目中Spring配置文件可能在Web容器中做加载,但原理都是一样)		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");		// 从容器中获取我们的控制层做测试		MyService myService = applicationContext.getBean(MyService.class);		myService.getMapList(15, "张三");		myService.add(new Customer("李四", 20, 100));		myService.update(new Customer("王五", 17, 30));	}}

#最近跟新

  • 增加了getByID功能,可以直接根据主键查找对象

#*注意,使用前提

  • 每张表都必须且只能包含一个“长整型”的主键。(其中对于SQLServer数据库,必须手动将主键设置为自增)
  • 每个与数据库对应的实体类,主键必须是long或者java.util.Long类型
  • 对于和数据库映射的日期时间类型统一为java.util.Date

#附件中有一个编译好的版本,可以直接使用


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap