124 Star 397 Fork 93

drinkjava2 / jSqlBox

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

English instructions please see "README_ENG.md"

jsqlbox-logo

Java全功能数据库持久层工具

maven code style

简介 | Intro

jSqlBox是一个全功能开源Java数据库持久层工具,在架构、功能、易用性等方面都不输于其它持久层工具,可以说,只要是与数据库操作相关的功能,jSqlBox都已具备,如DDL操作、分页、分库分表、声明式事务、分布式事务、关联映射查询等,所有这些功能都包含在一个1M大小的jar包中,不依赖任何第三方库。

文档 | Documentation

中文 | English | JavaDoc | PDF

jSqlBox与其它持久层工具对比

请见与其它DAO工具对比, 可以对jSqlBox的功能与特点有一个大概的了解。

主要特点 | Advantages

配置简单,没有依赖任何第三方库

在pom.xml中加入以下依赖即可使用。 如果需要查看或修改源码,甚至可以直接将jSqlBox的源码拷到项目目录里就可以直接使用了。

<dependency>
   <groupId>com.github.drinkjava2</groupId>
   <artifactId>jsqlbox</artifactId>  
   <version>5.0.15.jre8</version> <!-- 或最新版 -->
</dependency> 

直接在Java里写SQL

jSqlBox的最大特点是直接在Java里SQL,它的整个架构都是建立在这个基础上,这是它与其它DAO工具最大的区别。在Java里直接写SQL的最大优点是学习成本低,只要会SQL就可以立即上手使用,降低了学习难度。使用jSqlBox并不表示要使用它的全部功能,很多时候使用SQL就能处理业务,没必要引入复杂的ORM。

DbContext db= new DbContext(dataSource);
db.exe("insert into users (", //
          " name ,", par("Sam"), //一个参数写一行,方便维护
          notNull("address,", user.getAddress()), //空值判断
	  when(age>10, "age,", par(user.getAge())), //根据条件动态添加SQL片段
          " address ", par("Canada"), //
          ") ", valuesQuestions()); //自动根据参数个数补上 values(?,?...?)片段

在Java里写SQL谁都会,但是象jSqlBox这样做到极致的DAO工具并不多,个人认为jSqlBox这种方式是最能发挥原生SQL的威力,同时也是易学性、灵活性、可护展性最好的SQL写法。

借助字符串常量或Q类,可以写出支持重构的SQL

 QTbPriceSetting p=QTbPriceSetting.instance;
 DB.exe("insert into ",p," (", //
	p.id, ",", par(1200), //
	p.price, ",", par(80), //
	p.currency, ",", par("USD"), //
	p.created_at, par("2019-09-17 04:07:55"), //
	")", valuesQuestions());

Q类或包含字符串常量的实体类源码,可以使用jSqlBox的源码生成功能,从数据库直接生成,另外jSqlBox也支持从实体类或数据库中导出Excel格式的数据库表结构,详见jDialect的实体结构或数据库结构导出到Excel

架构合理,模块式架构,各个子模块(jBeanBox,jDbPro,jDialects,jTransaction)都可以脱离jSqlBox单独存在。

jSqlBox是源码包含模块式架构,目的是隔离功能点,并分享给其它工具重用。例如只想使用jDialcet数据库方言模块,可以在项目的pom.xml中加入:

<dependency>
    <groupId>com.github.drinkjava2</groupId>
    <artifactId>jdialects</artifactId>
    <version>5.0.13.jre8</version> <!--或最新版-->
</dependency>

基于jDialects模块,支持80多种数据库的分页、DDl脚本生成、从数据库生成实体源码、函数变换、主键生成等功能。

例如下面的SQL语句,就可以在多种数据库上使用而不需要更改源码,jSqlBox的jDialects模块自动处理与方言相关的DDL生成、分页、函数翻译。

DB.exe(DB.gctx().toCreateDDL(HelloWorld.class)); //根据实体生成DDL,创建数据库表
String sql=DB.trans("select concat('a','b','c'), current_time() from user_tb where age>0"); //根据方言对SQL函数翻译
DB.qryString(sql, " and price>100", pagin(1, 10));  //任意数据库分页只需要传入一个pagin对象

简洁的ActiveRecord模式

继承ActiveRRecord类,或只需要声明实现ActiveEntity接口,就可以实现ActiveRecord模式了:

public class User implements ActiveEntity{
 @UUID
 private String id;
 private String name;
 //getter &setter .....
}

//ActiveRecord模式
new User().loadById("张三").setUserAge(13).update(); 

强大的参数式设计。 拦截器、分页、模板、缓存、实体映射器等都可以当作参数拼接到SQL方法里去

例如SQL模板引擎可以当作参数传到SQL里,这样jSqlBox就具备了支持并以扩充各种SQL模板的功能:

SqlTemplateEngine TEMPLATE = BasicSqlTemplate.instance()
ctx2.exe(TEMPLATE, "update users set name=#{user.name}, address=:user.address", bind("user", tom));

再例如下面的SQL,只会执行一次,因为参数中有一个缓存拦截器,重复的SQL不再执行而是直接从缓存中取结果:

SimpleCacheHandler cache = new SimpleCacheHandler();
for (int i = 0; i < 10; i++)
   DB.qry(cache, new EntityListHandler(), DemoUser.class, "select u.* from DemoUser u where u.age>?", par(10));

为Java8开发环境提供多行文本支持,方便利用IDE快速定位到多行SQL文本上

public static class InsertDemoSQL extends Text {
/*-  
insert into demo
      (id, name) 
values( ?,  ?)
*/
}
//使用:
DB.exe(InsertDemoSQL.class, par("1", "Foo"));

实体关联查询

利用SQL的多表关联查询可以用一条SQL返回关联的对象结构。例如下例可以一次无递归查询树节点并装配成内存中对象树,其中的EntityNetHandler、alias, give等方法都是与实体关联映射相关的SQL参数:

Object[] targets = new Object[] { new EntityNetHandler(), TreeNode.class, TreeNode.class,
		alias("t", "p"), give("p", "t", "parent"), give("t", "p", "childs") };
EntityNet net = ctx.qry(targets, //深度树的海底捞算法
  "select t.**, t.pid as p_id from treenodetb t where t.line>=? and ",
      "t.line< (select min(line) from treenodetb where line>? and lvl<=?) ", par(line, line, lvl));
TreeNode node = net.pickOneEntity("t", d.getId());

不同于Hibernate和MyBatis复杂的配置,在jSqlBox中,实体关联查询只不过是一种参数略微复杂的SQL而已,随用随拼,不需要配置。

jSqlBox的主从表查询

jSqlBox的主从表查询是5.0.15版起新增的功能,将参数内嵌式SQL查询写成树状,即可实现类似GraphQL的结构化查询,输入和输出的树状结构一致,所见即所得。其优点有:
1.只需要编写针对单表查询的SQL,会自动按主从关联列名生成类似“id in (?, ?...?)”的SQL片段,并将最终查询结果组装成主从表树状结构。
2.采用纯Java和原生SQL,功能强,学习成本低。
3.没有直接输出为JSON,而是输出Map/List对象或Java实体对象,查询结果可以在后端继续修改。
4.可以直接利用Java的IDE格式化和语法检查功能,不需要第三方工具。
5.jSqlBox的内嵌式SQL参数、分页、分库分表、拦截器、事务等依然可以直接使用。
6.没有涉及安全、权限功能,无学习成本。安全、权限这些不属于ORM工具的职能,而应由后端的SpringSecurity/Shiro工具包或独立的Serverless/JsonAPI服务来提供。
7.如果结合我写的MyServerless项目使用,可以实现前端直接在html里书写Java、定制主从表多级查询并返回json, 实现类似GraphQL的功能,将业务逻辑前移到前端。
8.性能好,用"in"的方式进行数据库表的关联查询,不存在1+N问题。
9.源码简洁(实现这个功能仅用了300行源码,见GraphQuery.java)
使用示例:

        GraphQuery q1 = //
                $("addresstb as addresses", "where id>", que("a1"), " and id<", que("a5"), pagin(1, 10), //
                        $1("usertb", key("user"), ms("userId", "id"), $("userroletb as userRoleList", ms("id", "userId"), //
                                $("roletb as roleList", ms("rid", "id"), // ms方法也可以写成DB.masterSlave(),它的参数是主、从表的键名
                                        $("roleprivilegetb as rolePrivilegeList", ms("id", "rid"), //
                                                $1("privilegetb as privilege", ms("pid", "id")) //                                                 
                                        )//
                                )//
                        ), //
                                $1("select * from emailtb as email", ms("id", "userId"), one), //
                                $("addresstb as addressList", ms("id", "userId"), "and addressName like ?", par("addr%"))//
                        )//
                );
        GraphQuery q2 = //
                $("usertb as u", "where id>", que("u2"), pagin(1, 10), entity(User.class), //
                        $1("emailtb as emailMap", ms("id", "userId"), one), //
                        $("addresstb as addressList", ms("id", "userId"))//
                );
        Object result = DB.graphQuery(q1, q2); //result是查询结果
        String json = JsonUtil.toJSONFormatted(result); //输出为JSON文本

更多关于实体主从表查询的使用请详见用户手册。以上示例详见单元测试下的GraphQueryTest.java,示例结果输出如下:

{
   "addresses":[
      {
         "addressName":"address2",
         "id":"a2",
         "userId":"u2",
         "user":{
            "id":"u2",
            "userName":"user2",
            "userRoleList":[
               {
                  "id":"3i6yaxy2fusjkgisyfhypkti9",
                  "rid":"r1",
                  "userId":"u2",
                  "roleList":[
                     {
                        "id":"r1",
                        "roleName":"role1",
                        "rolePrivilegeList":[
                           {
                              "id":"b484ze4k44xemtkstehnprhxq",
                              "pid":"p1",
                              "rid":"r1",
                              "privilege":{
                                 "id":"p1",
                                 "privilegeName":"privilege1"
                              }
                           }
                        ]
                     }
                  ]
               },
            ......
      }
   ],
   "u":[
      {
         "id":"u3",
         "userName":"user3",
         "addressList":[
            {
               "addressName":"address3",
               "id":"a3",
               "userId":"u3"
            }
         ],
         "emailMap":{
            "emailName":"email5",
            "id":"e5",
            "userId":"u3"
         }
      },
      {
         "id":"u5",
         "userName":"user5",
         "addressList":[
            {
               "addressName":"address5",
               "id":"a5",
               "userId":"u5"
            }
         ]
      }
   ]
}

兼容主要JPA注解,支持在运行期动态更改配置

为了方便学习,jSqlBox兼容JPA实体类的以下主要注解:

@Entity, @Transient, @UniqueConstraint, @GenerationType, @Id, @Index, @SequenceGenerator, 
@GeneratedValue, @Table, @Column, @TableGenerator, @Version, @Enumerated, @Convert, @Temporal

jSql自带一些特殊实体注解如CreatedBy、LastModifiedBy、ShardTable、ShardDatabase、Snowflake等。 jSqlBox在运行期可动态更改实体关联配置,例如下面在运行期给一个pojo类动态配置UUID32主键,并更改它的name字段映射到address字段上:

TableModel m = TableModelUtils.entity2Model(PojoDemo.class);
m.column("id").pkey().uuid32();
m.column("name").setColumnName("address");
TableModelUtils.bindGlobalModel(PojoDemo.class, m);

jSqlBox自带多租户、主从、分库分表功能

jSqlBox的主从和分库分表功能除了默认的用实体Sharding注解操作外,还支持将分库分表方法作为参数直接传到SQL中使用,精准控制每一条SQL的分库分表:

//实体的分库分表
for (i:=0;i<100;i++)
   new TheUser().put("databaseId", i).insert(); 
   
//SQL中的分库分表   
db[2].exe(User.class, "insert into ", shardTB(tbID), shardDB(dbID)," (id, name, databaseId) 
          values(?,?,?)", par(tbID, "u1", dbID), USE_BOTH);

多租户功能可以根据IP地址等进行分库分表,这个和根据实体字段内容分库分表是有区别的,实际多租户要配置TenantGetter实例:

 public static class CustomTenantGetter implements TenantGetter {
        @Override
        public ImprovedQueryRunner getTenant() {
            return DB.gctx(); //通常是根据IP地址等,从treadlocal中取一个DbContext实例:
        } 
    }
 //启动阶段
 ctx = new DbContext(); 
 ctx.setTenantGetter(new CustomTenantGetter());

自带声明式事务,也支持使用Spring的事务

jSqlBox内置IOC/AOP工具,自带声明式事务功能,详见“事务配置”一节。如果是在Spring环境中,单独或与其它工具比如Hibernate/MyBatis混用,配置也非常简单,如下:

DbContext ctx = new DbContext(ds);
ctx.setConnectionManager(SpringTxConnectionManager.instance());
DbContext.setGlobalDbBoxContext(ctx);// 设定静态全局上下文

自带分布式事务功能

详见“分布式事务”一节,jSqlBox的分布式事务原理和Seata项目类似,可以自动生成回滚SQL,但jSqlBox的源码远比Seata简洁,因为jSqlBox是基于实体的CRUD生成回滚SQL,所以不需要考虑SQL兼容性这个问题。

不重复发明轮子,避开反模式

jSqlBox不重新发明轮子,使用DbUtils作为内核,以源码内含的方式包含到项目中,DbUtils是一个成熟、简洁、高效的JDBC工具。 jSqlBox尽量避免反模式,反模式就是花很多时间做没有意义的事,比如作者认为实体一对多、多对一的关联配置是个反模式,带来的性能、学习、维护问题往往比它解决的问题还要多,所以在jSqlBox中不支持一对多、多对一的JPA注解支持。 jSqlBox中也不存在用Java方法代替SQL关键字的这种做法,认为它也是一种反模式,比如下面这种写法:

List<S1UserPojo> userPojoList = dslContext.select()
            .from(S1_USER)
            .where(S1_USER.ID.eq(1))
            .fetch(r -> r.into(S1UserPojo.class));

只适合简单的CRUD,当逻辑稍微一复杂可读性、可维护性就非常差,还不如直接手写SQL来得方便。

入门 | First Example

以下示例演示了jSqlBox的基本配置和使用:

pom.xml中引入:
    <dependency>
      <groupId>com.github.drinkjava2</groupId>
       <artifactId>jsqlbox</artifactId> 
       <version>5.0.14.jre8</version> <!-- 或最新版 -->
    </dependency>

    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId> <!--H2内存数据库用于演示-->
      <version>1.3.176</version>
    </dependency>

在IDE里输入以下源程序:

import javax.sql.DataSource;
import org.h2.jdbcx.JdbcConnectionPool;
import static com.github.drinkjava2.jsqlbox.DB.*;
import com.github.drinkjava2.jdialects.annotation.jdia.UUID25;
import com.github.drinkjava2.jdialects.annotation.jpa.Id;
import com.github.drinkjava2.jsqlbox.ActiveEntity;
import com.github.drinkjava2.jsqlbox.DB;
import com.github.drinkjava2.jsqlbox.DbContext;

public class HelloWorld implements ActiveEntity<HelloWorld> {
  @Id
  @UUID25
  private String id;
  private String name;
  public String getId() {return id;}
  public void setId(String id) {this.id = id;}
  public String getName() {return name;}
  public HelloWorld setName(String name) {this.name = name;return this;}

    public static void main(String[] args) {
     DataSource ds = JdbcConnectionPool  //这个示例使用h2内存数据库
                     .create("jdbc:h2:mem:demo;MODE=MYSQL;TRACE_LEVEL_SYSTEM_OUT=0", "sa", "");
     DbContext ctx = new DbContext(ds);
     ctx.setAllowShowSQL(true);  //开启SQL日志输出
     DbContext.setGlobalDbContext(ctx);  //设定全局上下文
     ctx.quiteExecute(ctx.toDropAndCreateDDL(HelloWorld.class));  //生成DDL,建数据库表
     ctx.tx(() -> {  //开启事务
        HelloWorld h = new HelloWorld().setName("Foo").insert().putField("name", "Hello jSqlBox").update();
        System.out.println(DB.qryString("select name from HelloWorld where name like", que("H%"),
					" or name=", que("1"), " or name =", que("2")));
        h.delete();  //删除实体
     });
     ctx.executeDDL(ctx.toDropDDL(HelloWorld.class)); //删除数据库表
   }
}

上面这个演示包括了根据实体类生成DDL并执行、插入实体到数据库、执行更新、查询出结果、即打印出"Hello jSqlBox"、删除实体、删除数据库。 示例中的实体类只需要声明接口(限Java8版)。查询语句使用了jSqlBox独创的参数内嵌式SQL写法,可以自由拼接复杂的条件SQL,也不用考虑参数和问号对齐的问题了。
上例中的事务语法也可以写成传统的方式:

        try {
            ctx.startTrans(); //开启事务
            HelloWorld h = new HelloWorld().setName("Foo").insert();
            ctx.commitTrans(); //提交事务
        } catch (Exception e) { 
            ctx.rollbackTrans(); //回滚事务
        }

因为开启了日志输出,可以看到命令行打印出的SQL执行日志:

SQL: drop table HelloWorld if exists
PAR: []
SQL: create table HelloWorld ( id varchar(250),name varchar(250), primary key (id))
PAR: []
SQL: insert into HelloWorld (name, id)  values(?,?)
PAR: [Foo, emeai4bfdsciufuuteb9a7nmo]
SQL: update HelloWorld set name=?  where id=?
PAR: [Hello jSqlBox, emeai4bfdsciufuuteb9a7nmo]
SQL: select name from HelloWorld where name like? or name=? or name =?
PAR: [H%, 1, 2]
SQL: delete from HelloWorld where id=? 
PAR: [emeai4bfdsciufuuteb9a7nmo]
SQL: drop table HelloWorld if exists
PAR: []

更全面的功能点介绍和使用,请详见jSqlBox的用户手册

范例 | Demo

以下范例位于jSqlBox的demo目录下:

  • jbooox 这是一个微型Web演示项目,基于三个开源项目jBeanBox、jSqlBox、jWebBox的整合。
  • jsqlbox-actframework 演示jSqlBox与ActFramework框架的整合,分别展示利用jBeanBox和Guice来实现声明式事务。
  • jsqlbox-jfinal 演示jSqlBox与jFinal的整合,用jSqlBox替换掉jFinal自带的DAO工具。
  • jSqlBox-Spring 演示jSqlBox在Spring+Tomcat环境下的配置和使用
  • jsqlbox-springboot 演示jSqlBox在SpringBoot环境下的配置和使用。
  • jsqlbox-mybatis 演示在SpringBoot环境下jSqlBox和MyBatis的混合使用。
  • jsqlbox-beetl 演示如何在jSqlBox中自定义SQL模板引擎,此演示使用Beetl作为SQL模板。
  • jsqlbox-qclass 演示如何利用静态变量或Q类来写出支持重构的SQL

相关开源项目 | Related Projects

期望 | Futures

欢迎发issue提出更好的意见或提交PR,帮助完善项目

版权 | License

Apache 2.0

关注我 | About Me

码云
Github

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

简介

Java全功能数据库持久层工具 展开 收起
Java
Apache-2.0
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Java
1
https://gitee.com/drinkjava2/jsqlbox.git
git@gitee.com:drinkjava2/jsqlbox.git
drinkjava2
jsqlbox
jSqlBox
master

搜索帮助

14c37bed 8189591 565d56ea 8189591