ThinkJDBC 一行代码搞定数据库操作开源项目

我要开发同款
匿名用户2018年04月21日
35阅读
开发技术Java
所属分类数据库相关、数据库调整和优化
授权协议Apache

作品详情

    

1简介

ThinkJD,又名ThinkJDBC,一个简洁而强大的开源JDBC操作库。你可以使用Java像ThinkPHP框架的M方法一样,一行代码搞定数据库操作。ThinkJD会自动管理数据库连接,默认使用完毕或程序异常都会关闭连接以免造成内存溢出。也可以设置手动关闭以复用Connection连接,无需传入连接实例参数,ThinkJD内部已做多线程安全处理,详见【0x0A多线程安全】。

特性核心jar包只有30多KB支持复杂SQL语句以及直接执行SQL语句自动管理数据库连接支持增删改查ORM映射支持字段注解映射主键、自增、是否ORM字段等属性配置动态设置>注解设置>全局设置数据库连接多线程安全支持数据库连接池简易的事务操作支持调试模式,输出SQL语句基于DBUtils,Apache出品,底层质量有保障先睹为快://数据库配置(只需调用一次)D.setDbConfig("jdbc:mysql://127.0.0.1:3306/DbName?characterEncoding=UTF-8","root","root");//JavaBean模式,自动获取表名、主键、自增属性、字段名和数据Useruser=newUser();user.setAge(10);user.setName("Hello");user.setSex(true);//插入数据longid=D.M(user).add();//查询数据user=D.M(User.class).find(id);//更新数据user.setSex(false);D.M(user).field("sex").save();//不指定字段名默认更新JavaBean的所有非空属性//删除数据D.M(user).delete();//D.M(User.class).delete(id);//Table模式,手动指定表名、主键、自增属性、字段名和数据//插入数据longid=D.M("user").field("name,weight").data("Tom",60).add();//更新数据D.M("user").field("name,weight").data("Tom",100).where("id=?",id).save();//查询数据user=D.M(User.class).find(id);//删除数据D.M("user").delete(id);项目主页

https://gitee.com/Leytton/ThinkJD (码云) https://github.com/Leytton/ThinkJD (Github)

测试项目

https://github.com/Leytton/ThinkJD_Demo

2使用方法0x01添加依赖导入Jar包

引入ThinkJDBC-x.x.x-core.jar核心库和以下两个依赖库:

mysql-connector-java-5.1.39.jarcommons-dbutils-1.6.jar

或者

Maven<dependency><groupId>com.llqqww</groupId><artifactId>thinkjdbc</artifactId><version>1.4.4_13</version></dependency>0x02定义数据库

ThinkJD支持直接定义用户名密码访问数据库,也支持使用Hikari、C3P0等数据库连接池。

数据库连接方式有三种:

(1)配置文件方式

在项目根目录下添加文件(跟Hikari配置文件格式一样)

程序第一次启动时会自动加载读取配置文件,如果文件不存在则忽略。【V1.2.4_5增加功能】

thinkjdbc.properties

jdbcUrl=jdbc:mysql://127.0.0.1:3306/thinkjdbc?useUnicode=true&characterEncoding=UTF-8dataSource.user=rootdataSource.password=root(2)帐号密码方式D.setDbConfig("jdbc:mysql://127.0.0.1:3306/database?useUnicode=true&characterEncoding=UTF-8","root","root");(3)使用数据库连接池

例如使用Hikari连接池:

HikariConfigconfig=newHikariConfig("/hikari.properties");HikariDataSourcedataSource=newHikariDataSource(config);D.setDataSource(dataSource);

注:如果定义了数据库连接池,ThinkJD会优先使用。

(3)配置表前缀

只需调用一次,配置表前缀不是必需的

D.setTablePrefix("jd_");//D.M('user')D.M(User.class)将会操作`jd_user`表

注:D.M('user').prefix('jd_')方法可单独指定表前缀【V1.2.3新增】

0x03连贯操作操作参数示例说明tabletable(Stringtable)table("user") pkpk(Stringkey)pk("id") autoIncautoInc(booleanisPkAutoInc)autoInc(false) joinjoin(Stringjoin)join("leftjoinmachineonuser.id=user_idandmachine_status=1") fieldfield(Stringfiled)field("id,username") datadata(Object...dataParam)data(11,"Leytton") setIncsetInc(Stringkey,longnum)setInc("gold",5)//gold=gold+5 setDecsetDec(Stringkey,longnum)setDec("gold",5)//gold=gold-5 where①where(Stringwhere)②where(Stringwhere,Object...whereParam)①where("id=1111andusername='Leytton'")②where("id=?andusername=?",1111,"Leytton") groupgroup(Stringgroup)group("type") havinghaving(Stringhaving)having("id>1234") orderorder(Stringorder)order("iddesc") ascasc(Stringkey)asc("id") descdesc(Stringkey)desc("id") pagepage(longpage,longrows)page(1,10) limit①limit(longrows)②limit(longoffset,longrows)①limit(10)②limit(1,10) unionunion(Stringunion,BooleanisAll)①union("select*fromuser_twowhereid>1234",false)②union("select*fromuser_twowhereid>1234",true) 0x04查询数据操作参数说明select①<T>List<T>select()②<T>List<T>select(Stringkey,Objectvalue) find①<T>Tfind()②<T>Tfind(Objectvalue)③<T>Tfind(Stringkey,Objectvalue) count①longcount()②longcount(Stringfield) maxdoublemax(Stringfield) mindoublemin(Stringfield) avgdoubleavg(Stringfield) sumdoublesum(Stringfield) //find查询//selectid,namefromjd_userwhereid>4orderbyidasclimit0,1Userres=D.M(User.class).field("id,name").where("id>?",4).order("idasc").find();//find根据id查询//select*fromjd_userwhereid=3limit0,1Useruser=D.M(User.class).find(3);//find根据字段查询//select*fromjd_userwherename='Tom'limit0,1Useruser=D.M(User.class).fetchSql(true).find("name","Bob");//where,field过滤//selectid,name,weightfromjd_userwhereid>3List<User>res=D.M(User.class).field("id,name,weight").where("id>3").select();//group分组查询//selectsex,sum(weight)asweight,avg(age)asage,count(id)asnumfromjd_userwhereid>5groupbysexorderbysexdesclimit0,10res=D.M(User.class).field("sex,sum(weight)asweight,avg(age)asage,count(id)asnum").where("id>?",5).group("sex").order("sexdesc").page(1,10).select();//join联表查询//selectjd_user.id,name,weight,sum(gold)asnumfromjd_userleftjoinjd_goldonuser_id=jd_user.idwherejd_user.id>3groupbyjd_user.idres=D.M(User.class).field("jd_user.id,name,weight,sum(gold)asnum").join("leftjoinjd_goldonuser_id=jd_user.id").where("jd_user.id>3").group("jd_user.id").select();//union联表查询//(selectid,namefromjd_userwhereid=4)unionall(selectid,namefromjd_userwhereid<3)union(selectid,namefromjd_userwhereid=3)res=D.M(User.class).field("id,name").where("id=4").union("selectid,namefromjd_userwhereid<3",true).union("selectid,namefromjd_userwhereid=3",false).select();//统计查询longnum=newM(User.class).where("id>3").count();num=D.M(User.class).fetchSql(true).where("id>3").count("id");num=(long)D.M(User.class).fetchSql(false).where("id<0").max("id");num=(long)D.M(User.class).where("id<3").max("id");num=(long)D.M(User.class).min("id");num=(long)D.M(User.class).where("id>3").min("id");num=(long)D.M(User.class).fetchSql(false).where("id>3").avg("id");doubleavg=D.M(User.class).fetchSql(false).where("id>3").avg("id");num=(long)D.M(User.class).where("id>13441").sum("age");

通过调用fetchSql(true)方法,可以获取到 ThinkJD产生的SQL语句(Exception形式)并且不会执行数据库操作。 

user表结构:

字段名数据类型备注idint用户id,自增长主键namevarchar用户名agetinyint年龄weightfloat体重sextinyint性别0女/1男timeint时间

select()和 find()查询结果封装到JavaBean里返回,JavaBean可使用注解映射数据库字段。

注意:墙裂建议JavaBean字段基础数据类型用【Integer、Long、Boolean、Float、Double、Byte、Short、Char】不要使用【integer、long、boolean、float、double、byte、short、char】,因为前者可以赋值为null而后者不行(null时为0),所以获取到的值是不准确的。ThinkJD的save更新等操作通过判断属性值不为null则加入数据库更新字段队列。ThinkJD会自动检测以上不符合的数据类型并发出警告。如需关闭调用D.setCheckField(false);

//@Table(name="user")默认类名为表名,可注解重定义publicclassUser{//@Column(isKey=true)默认id为主键、isAutoInc=true自增,可注解重定义privateLongid;privateIntegerage;//@Column(name="user_name")默认属性名为表字段,可注解重定义privateStringname;privateFloatweight;privateBooleansex;@Column(isColumn=false)privateIntegernum;privateLongtime;publicLonggetId(){returnid;}publicvoidsetId(Longid){this.id=id;}publicIntegergetAge(){returnage;}publicvoidsetAge(Integerage){this.age=age;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicFloatgetWeight(){returnweight;}publicvoidsetWeight(Floatweight){this.weight=weight;}publicBooleangetSex(){returnsex;}publicvoidsetSex(Booleansex){this.sex=sex;}publicIntegergetNum(){returnnum;}publicvoidsetNum(Integernum){this.num=num;}publicLonggetTime(){returntime;}publicvoidsetTime(Longtime){this.time=time;}}0x05插入数据操作参数说明addlongadd()Table模式前提方法:data()返回自动生成的主键值;/*指定插入字段*/longid=D.M(User.class).field("name,weight").data("Tom",60).add();/*不指定插入字段,按表字段顺序插入*/id=D.M("user").data(null,"Tom",60,...).add();/*使用javaBean半自动模式,自动获取表名、主键、字段名,给定data按javaBean属性顺序插入,生成的sql语句如下*insertintojd_user(age,name,weight,sex,time)values(?,?,?,...)*/id=D.M(User.class).data("Tom",60,...).add();//使用javaBean全自动模式,自动获取表名、主键、字段名和数据Useruser=newUser();user.setId(5);user.setAge(10);user.setName("Hello");//insertintojd_user(age,name)values(?,?)Params[10,Hello]num=D.M(user).add();//insertintojd_user(name)values(?)Params[Hello]num=D.M(user).field("name").add();//insertintojd_user(id,age,name)values(?,?,?)Params[5,10,Hello]num=D.M(user).autoInc(false).add();0x06更新数据操作参数说明savelongsave()Table模式前提方法:data(),where();返回执行生效行数longnum=D.M("user").field("name,weight").data("Mike",100).where("id=?",1234).save();Useruser=newUser();user.setId(5);user.setAge(10);user.setName("Hello");//updatejd_usersetage=?,name=?whereid=?;Params[10,Hello,5]num=D.M(user).save();//updatejd_usersetname=?whereid=?;Params[Hello,5]num=D.M(user).field("name").save();//updatejd_usersetid=?,age=?,name=?whereid=?;Params[5,10,Hello,4]id=D.M(user).autoInc(false).fetchSql(true).where("id=?",user.getId()-1).save();0x07删除数据操作参数说明deletelongdelete()Table模式前提方法:where()返回执行生效行数

注:为防止误删除,where条件不能为空。

longnum=D.M("user").delete(5);//默认为id=?num=D.M("user").delete("time",1523681398);//time=?num=D.M(User.class).where("id>=?",13421).delete();//JavaBean模式Useruser=newUser();user.setId(10L);longnum=D.M(user).delete();0x08执行SQL操作参数说明executevoidexecute(String...sqls)直接执行SQL语句D.M().execute(sql1[sql2,sql3...]);0x09事务支持

数据库表引擎应该为InnoDB以支持事务操作。 代码示例:

Connectionconn=null;try{//获取已开启事务的数据库连接conn=D.M().startTrans();//使用事务连接操作数据库longid=newM("gold").trans(conn).field("user_id,gold,type,time").data(3,5,0,System.currentTimeMillis()/1000).add();System.out.println(id);if(id>0){thrownewSQLException("TransactionRollbackTest");}id=newM("gold").trans(conn).field("user_id,gold,type,time").data(3,5,0,System.currentTimeMillis()/1000).add();System.out.println(id);//提交事务D.M().commit(conn);}catch(SQLExceptione){e.printStackTrace();try{//事务回滚D.M().rollback(conn);}catch(SQLExceptione1){e1.printStackTrace();}}

 

0x0A多线程安全

【V1.4.4_12功能】

/*设置数据库操作完毕后不自动关闭*此处是为了提高数据库操作性能,不用频繁地获取和关闭连接,同一线程内ThinkJD会使用同一连接;*默认自动关闭连接的话,每次操作都会获取一个新的Connection,使用完毕立即自动关闭*/D.setAutoClose(false);newThread(newRunnable(){@Overridepublicvoidrun(){Goldgold=newGold();gold.setUser_id(1L);gold.setGold(5);gold.setGold_type(0);try{D.M(gold).add();D.M(gold).add();}catch(SQLExceptione){D.closeConn();e.printStackTrace();}}},"Thread_1").start();newThread(newRunnable(){@Overridepublicvoidrun(){Goldgold=newGold();gold.setUser_id(2L);gold.setGold(5);gold.setGold_type(0);try{D.M(gold).add();D.M(gold).add();}catch(SQLExceptione){D.closeConn();e.printStackTrace();}}},"Thread_2").start();

获取数据库连接处输出日志为:

Thread:Thread_1,conn==null:trueThread:Thread_2,conn==null:trueThread:Thread_2,conn==null:falseThread:Thread_1,conn==null:false

由此可见,线程1第一次操作数据库时conn为空,会获取一个新的conn,下次操作时conn不为空可以直接使用,直到调用D.closeConn();后conn才会关闭。线程2也是如此。

3许可证

ApacheLicense2.0 免费用于个人和商业,请放心食用:)

4关于

如果喜欢的话,请点个赞让我知道哦~在找到比它用得更顺手的JDBC库之前,这个项目会持续更新。

声明:本文仅代表作者观点,不代表本站立场。如果侵犯到您的合法权益,请联系我们删除侵权资源!如果遇到资源链接失效,请您通过评论或工单的方式通知管理员。未经允许,不得转载,本站所有资源文章禁止商业使用运营!
下载安装【程序员客栈】APP
实时对接需求、及时收发消息、丰富的开放项目需求、随时随地查看项目状态

评论