• Stars
    star
    192
  • Rank 201,579 (Top 4 %)
  • Language
    Java
  • Created almost 11 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

an easy jdbc sql framework of an alternative to ibatis

eql

Build Status Coverage Status Maven Central License

An easy framework of java JDBC to be an alternative to ibatis/mybatis.中文版

I don't like XML in ibatis.

  • excuse 1:
<select id="selectAB">
<![CDATA[
   SELELCT A,B
   FROM SOME_TABLE
   WHERE A > #a#
]]>
</select>

Wooh, for a simple sql of only three lines, we need add a CDATA block to use > (I always forget how to write CDATA, and every time I have to lookup XML CDATA reference). It's so bad. And also the select is redundant because the SQL itself is telling us it is a SELECT SQL and not some others.

  • excuse 2:

When two or more members are working on the same XML file, only one bad SQL will corrupt all the SQLs in the same file:

<update id="xxx">
SELECT 1 FROM DUAL WHERE 1 > 0
</update>

Ooh, that is "one rotten apple could ruin a whole barrel of apples."

  • excuse 3:

Every time, when I code with ibatis, I forget how to begin (eg. how to create Sqlmap and how to write valid ibatis xml) and have to copy some initial code from others.

  • excuse 4:

There is no else in its dynamic. I have to write like:

<select id="xxx">
   SELECT 1 FROM DUAL
   WHERE 1 = 1
   <isEmpty property="name">
     AND name = #name#
   </isEmpty>
   <isNotEmpty property="name">
     AND id = #id#
   </isNotEmpty>
</select>
  • excuse 5:

I don't like XML. I like free text and freedom. And so I created EQL which is really very easy.

One minute tutorial

  • copy eql-DEFAULT.properties to your classpath eql and do some changes for your database connection info such as url, password and username.
  • create com/xxx/Demo.java.
  • create com/xxx/Demo.eql(keep the same package and base filename) in classpath.
  • write following code in com.xxx.Demo main method:
String str = new Eql().selectFirst("demo").execute();
  • write an eql in Demo.eql
-- [demo]
select 'X' from dual
  • that's all. and you see it is very simple.

Return one row

Map<String, String> row = new Eql().selectFirst("oneRow").execute();
-- [oneRow]
select 'X', 'Y' from dual

Return a Javabean

XYBean xy = new Eql().selectFirst("javabean").execute();
-- [javabean returnType=XYBean]
select 'X', 'Y' from dual

Return rows

List<XYBean> xys = new Eql().select("rows").
             .returnType(XYBean.class)
             .execute();
-- [rows]
select 'X' X, 'Y' Y from dual
union
select 'A' X, 'B' Y from dual

With parameters in sequence

  • example 1
String x = new Eql().selectFirst("autoSeq1")
          .params("x")
          .execute();
-- [autoSeq1]
select 'X' from dual
where 'x' = '##'
  • example 2
String x = new Eql().selectFirst("autoSeq2")
          .params("x", "y")
          .execute();
-- [autoSeq2]
select 'X' from dual
where 'x' = '##'
and 'y' = '##'
  • example 3
String x = new Eql().selectFirst("autoSeq3")
          .params("y", "x")
          .execute();
-- [autoSeq3]
select 'X' from dual
where 'x' = '#2#'
and 'y' = '#1#'

With parameters by properties name

  • example 1
String x = new Eql().selectFirst("bean")
       .params(new XyBean("x", "y"))
       .execute();
-- [bean]
select 'X' from dual
where 'x' = '#x#'
and 'y' = '#y#'
  • example 2
String x = new Eql().selectFirst("map")
        .params(mapOf("x", "a", "y", "b"))
        .execute();
-- [map]
select 'X' from dual
where 'a' = '#x#'
and 'b' = '#y#'
  • example 3
String x = new Eql().selectFirst("map")
        .params("a", "b")
        .execute();
-- [map]
select 'X' from dual
where 'a' = '#_1#'
and 'b' = '#_2#'

In above example, the _1 and _2 are used, they are called built-in parameters. More built-in parameters list here:

  1. _time current timestamp, type: java.sql.Timestamp
  2. _date current date, type:java.util.Date
  3. _host current hostname
  4. _ip current ip
  5. _params currrent params array
  6. _paramsCount length of current params array
  7. _1,_2,_3,... the param in sequence
  8. _dynamics current dynamics array
  9. _dynamicsCount lenght of current dynamics array
  10. _databaseId, oracle/mysql/h2/db2/sqlserver

Dynamic sql

Eql's dynamic sql is now base on OGNL expression.

if

// real sql will be:
//   select 'X' from dual where 'a' = ?
// and with one bound param "a"
String x = new Eql().selectFirst("ifDemo")
          .params(mapOf("x", "a"))
          .execute();

// real sql will be:
//   select 'X' from dual
String y = new Eql().selectFirst("ifDemo")
          .params(mapOf("x", "b"))
          .execute();
-- [ifDemo]
select 'X' from dual
-- if x == "a"
where 'a' = '#x#'
-- end

-- [ifDemo2]
select 'X' from dual
-- if x == "a"
where 'a' = '#x#'
-- else if x == "b"
where 'b' = '#x#'
-- else
where 'c' = '##'
-- end

-- or use more compact syntax

-- [ifDemo]
select 'X' from dual /* if x == "a" */  where 'a' = '#x#' /* end */

iff

-- [ifDemo]
select 'X' from dual
-- iff x == "a"
where 'a' = '#x#'

-- or use more compact syntax

-- [ifDemo]
select 'X' from dual /* iff x == "a" */  where 'a' = '#x#'

to use STATIC fields:

public class OgnlStaticTest {
    public static String STATE = "102";

    @Test
    public void test() {
        String str = new Eql("mysql").id("ognlStatic").limit(1)
                .params(ImmutableMap.of("state", "102", "x", "y"))
                .execute();
        assertThat(str, is(nullValue()));

        str = new Eql("mysql").id("ognlStatic").limit(1)
                .params(ImmutableMap.of("state", "103", "x", "x"))
                .execute();
        assertThat(str, is("X"));
    }
}
-- [ognlStatic]
select 'X'
from DUAL
-- iff state == @org.n3r.eql.OgnlStaticTest@STATE
where 'x' = '#x#'

switch

-- [switchSelect returnType=org.n3r.eql.SimpleTest$Bean]
SELECT A,B,C,D,E
FROM EQL_TEST
WHERE
-- switch a
--   case 1
  A = 1
--   case 2
  A = 2
-- end

-- or with default keyword

-- [switchSelectWithDefault returnType=org.n3r.eql.SimpleTest$Bean]
SELECT A,B,C,D,E
FROM eql_TEST
WHERE
-- switch a
--   case 1
   A = 1
--   case 2
   A = 2
--   default
   A = 3
-- end

for

Map<String, Object> map = Maps.newHashMap();
map.put("list", ImmutableList.of("a", "b", "x"));

String str = new Eql().selectFirst("for1").params(map).execute();
assertThat(str, is("x"));
-- [for1]
SELECT 'x'
FROM DUAL
WHERE 'x' in
-- for item=item index=index collection=list open=( separator=, close=)
#item#
-- end

is(Not)Null/is(Not)Empty/is(Not)Blank

-- [isEmpty]
SELECT B
FROM eql_TEST
-- isEmpty a
WHERE A in (1,2)
-- else
WHERE A in (3,4)
-- end

-- [isNotEmpty]
SELECT B
FROM eql_TEST
-- isNotEmpty a
WHERE A = '#a#'
-- end

in statement in sql

SELECT NAME FROM EQL_IN WHERE ID IN (/* in _1 */)
List<String> names = new Eql().params(Lists.newArrayList("1", "2")).execute();

trim

-- [updateAuthor]
update author
-- trim prefix=SET suffixOverrides=,
  -- iff username != null
         username='#username#',
  -- iff password != null
         PASSWORD='#password#',
  -- iff email != null
         email='#email#',
  -- iff bio != null
          bio='#bio#',
-- end
where id='#id#'

-- [selectBlog]
SELECT STATE FROM BLOG
-- trim prefix=WHERE prefixOverrides=AND|OR
   -- iff state != null
          state = '#state#'
   -- iff title != null
      AND title like '#title#'
   -- iff author != null and author.name != null
      AND author_name like '#author.name#'
-- end
GROUP BY STATE

Pagination support

EqlPage page = new EqlPage(3, 2);
List<SimpleTest.Bean> beans = new Eql().id("testPage")
   .returnType(SimpleTest.Bean.class)
   .limit(page)
   .params("DC")
   .execute();
assertThat(page.getTotalRows(), is(10));
-- [testPage]
SELECT A,B,C,D,E
FROM eql_TEST
WHERE C = '##'

Dynamic table name

String str = new Eql().selectFirst("replace1")
   .params("x").dynamics("DUAL").execute();
assertThat(str, is("x"));

str = new Eql().selectFirst("replace2").params("x")
   .dynamics(ImmutableMap.of("table", "DUAL")).execute();
assertThat(str, is("x"));
-- [replace1]
SELECT 'x'
FROM $$
WHERE 'x' = '##'


-- [replace2]
SELECT 'x'
FROM $table$
WHERE 'x' = '##'

Batch execute

Eql eql = new Eql();
eql.startBatch(/*batchSize*/10);
for (int i = 0; i < 10; ++i) {
    String orderNo = randLetters(10);
    String userId = randLetters(10);
    int prizeItem = randInt(10);
    int ret = eql.insert("insertPrizeBingoo")
           .params(orderNo, "Olympic", "" + prizeItem, userId)
           .execute();

    assertEquals(0, ret);
}

eql.executeBatch();
-- [insertPrizeBingoo]
INSERT INTO EQL_TEST_BINGOO(ORDER_NO, ACTIVITY_ID, ITEM_ID, USER_ID, BINGOO_TIME)
VALUES(##, ##, ##, ##, SYSDATE)

Like option support

-- [likeDemo]
select 'x' from demo where name like '#:Like#'

-- [leftLikeDemo]
select 'x' from demo where name like '#:LeftLike#'

-- [rightLikeDemo]
select 'x' from demo where name like '#:RightLike#'
new Eql().id("likeDemo").params("b").execute();
// 16:12:51.316 [main] DEBUG org.n3r.eql.Eql - prepare sql likeDemo: select 'x' from demo where name like ?
// 16:12:51.317 [main] DEBUG org.n3r.eql.map.EqlRun - param: [%b%]

new Eql().id("leftLikeDemo").params("c").execute();
// 16:12:51.326 [main] DEBUG org.n3r.eql.Eql - prepare sql leftLikeDemo: select 'x' from demo where name like ?
// 16:12:51.326 [main] DEBUG org.n3r.eql.map.EqlRun - param: [%c]

new Eql().id("rightLikeDemo").params("a").execute();
// 16:12:51.331 [main] DEBUG org.n3r.eql.Eql - prepare sql rightLikeDemo: select 'x' from demo where name like ?
// 16:12:51.331 [main] DEBUG org.n3r.eql.map.EqlRun - param: [a%]

Oracle Blob support

public void testOracleBlob() {
    new Eqll().id("insertBlob").params("中华人民共和国").execute();
    byte[] bytes = new Eqll().id("selectBlob").limit(1).execute();
    assertThat(new String(bytes, Charsets.UTF_8), is("中华人民共和国"));

    String ret = new Eqll().id("selectBlobString").limit(1).execute();
    assertThat(ret, is("中华人民共和国"));

    AsResult asResult = new Eqll().id("selectBlobAsResult").limit(1).execute();
    assertThat(asResult.getSeq(), is(1));
    assertThat(asResult.getRemark(), is("中华人民共和国"));

    Integer effectedRows = new Eqll().id("updateBlob").params("台湾省").execute();
    assertThat(effectedRows, is(1));
    ret = new Eqll().id("selectBlobString").limit(1).execute();
    assertThat(ret, is("台湾省"));
}

public static class AsResult {
    private String state;
    private String remark;
    private int seq;

    // setters ang getters
}
-- [insertBlob onerr=resume]
DROP TABLE eql_BLOB;
CREATE TABLE eql_BLOB (BOB BLOB);
INSERT INTO eql_BLOB(BOB) VALUES(#:LOB#)

-- [selectBlob]
SELECT BOB FROM eql_BLOB

-- [selectBlobString returnType=string]
SELECT BOB FROM eql_BLOB


-- [selectBlobAsResult returnType=org.n3r.eql.JavaBlobTest$AsResult]
SELECT 1 as seq, BOB as remark FROM eql_BLOB

-- [updateBlob]
UPDATE eql_BLOB SET BOB = '#:LOB#'

Diamond-miner support example

Eql also can be loaded from diamond. First create eql/eql-diamond.properties on classpath like:

sql.resource.loader=org.n3r.eql.diamond.DiamondEqlResourceLoader

transactionType=jdbc
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
user=orcl
password=orcl

As you see, we redefined sql resource loader to diamond-specific. And then add a config in diamond:

group=EQL
dataId=org.n3r.eql.DiamondTest.eql
content=

-- [diamondDemo]
SELECT 'Hello' FROM DUAL

And then in java code

String str = new Eql("diamond").selectFirst("diamondDemo").execute();
System.out.println(str);

Reuse jdbc statements to select/update repeatedly.

Eql eql = new Eql().id("selectStmt");
ESelectStmt selectStmt = eql.selectStmt();

selectStmt.executeQuery(3);
String str = selectStmt.next();
assertThat(str, is("CC"));
assertThat(selectStmt.next(), is(nullValue()));

selectStmt.executeQuery(4);
str = selectStmt.next();
assertThat(str, is("DC"));
assertThat(selectStmt.next(), is(nullValue()));

selectStmt.close();
eql.close();
Eql eql = new Eql().id("updateStmt");
EUpdateStmt updateStmt = eql.updateStmt();

int rows = updateStmt.update(3, "Bingoo");
assertThat(rows, is(1));

rows = updateStmt.update(4, "Dingoo");
assertThat(rows, is(1));

updateStmt.close();
eql.close();
-- [selectStmt]
SELECT C
FROM eql_TEST
WHERE A = '##'

-- [updateStmt]
UPDATE eql_TEST
SET C = '#2#'
WHERE A = '#1#'

Custom result mapper example

import org.n3r.eql.map.EqlRowMapper;

public static class MyMapper implements EqlRowMapper {
    private String name;

    @Override
    public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
        name = rs.getString(1);
        return null;
    }

    public String getName() {
        return name;
    }
}

@Test
public void test() {
    MyMapper myMapper = new MyMapper();
    new Eql().returnType(myMapper).execute("SELECT 'X' FROM DUAL");
    assertThat(myMapper.getName(), is("X"));
}

Custom config support

Eqll.choose(new EqlJdbcConfig("oracle.jdbc.driver.OracleDriver",
        "jdbc:oracle:thin:@127.0.0.1:1521:orcl", "orcl", "orcl"));

Timestamp ts = new Eqll().limit(1).execute("SELECT SYSDATE FROM DUAL");

// or
Eqll.choose(new EqlPropertiesConfig(
        EqlConfigKeys.DRIVER + "=oracle.jdbc.driver.OracleDriver\n" +
        EqlConfigKeys.URL + "=jdbc:oracle:thin:@127.0.0.1:1521:orcl\n" +
        EqlConfigKeys.USER + "=orcl\n" +
        EqlConfigKeys.PASSWORD + "=orcl\n"));

Supported configs are listed below:

connection.impl

  • Meaning: Full qualified class name(FQCN) that implemented org.n3r.eql.trans.EqlConnection interface.
  • Default: When jndiName is set, use org.n3r.eql.trans.EqlJndiConnection, otherwise org.n3r.eql.trans.EqlSimpleConnection.
  • Samples: org.n3r.eql.trans.EqlC3p0Connection or your custom implementation.

jndiName

  • Meaning: Specified JNDI name to use JNDI data source.
  • Default: N/A.
  • Samples: N/A.

java.naming.factory.initial

  • Meaning: Used together with jndiName.
  • Default: None.
  • Samples: weblogic.jndi.WLInitialContextFactory

java.naming.provider.url

  • Meaning: Used together with jndiName.
  • Default: None.
  • Samples: t3://127.0.0.1:7001/

transactionType

  • Meaning: Used together with jndiName.
  • Default: JDBC.
  • Samples: JTA.

driver

  • Meaning: JDBC driver name.
  • Default: None.
  • Samples: oracle.jdbc.driver.OracleDrivercom.mysql.jdbc.Driver, and ...

url

  • Meaning: JDBC url.
  • Default: None
  • Samples: jdbc:oracle:thin:@127.0.0.1:1521:orcl, jdbc:mysql://localhost:3306/diamond?useUnicode=true&&characterEncoding=UTF-8&connectTimeout=1000&autoReconnect=true

user

  • Meaning: JDBC username.
  • Default: None.
  • Samples: orcl.

password

  • Meaning: JDBC password.
  • Default: None.
  • Samples: orcl.

expression.evaluator

  • Meaning: Full quantified class name which implements org.n3r.eql.base.ExpressionEvaluator.
  • Default: org.n3r.eql.impl.OgnlEvaluator.
  • Samples: customed implementation.

sql.resource.loader

  • Meaning: EQL resource loader. FQCN which implements org.n3r.eql.base.EqlResourceLoader.
  • Default: org.n3r.eql.impl.FileEqlResourceLoader which read eql file of the same package and same base name with Eql's used java class.
  • Samples: org.n3r.eql.diamond.DiamondEqlResourceLoader or custom implementation.

dynamic.language.driver

  • Meaning: EQL dynamic support language driver. FQCN which implements org.n3r.eql.base.DynamicLanguageDriver.
  • Default: org.n3r.eql.impl.DefaultDynamicLanguageDriver which use SQL special comment to achieve dynamic SQL.
  • Samples: org.n3r.eql.impl.FreemarkerDynamicLanguageDriver or custom implementation.

sql.parse.lazy

  • Meaning: Parse dynamic EQL while execution or not.
  • Default: false.
  • Samples: true or yes.

Integrated with diamond-client

Read connection configuration from diamond

  • Add a diamond stone:
group=EqlConfig,dataId=DEFAULT,content=
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
user=orcl
password=orcl
  • Use Dql to replace Eql to work with diamond connection configuration.
// read diamand content of group=EqlConfig, dataId=DEFAULT as connection config
new Dql().id("xxx").execute();

// read diamond content of group=EqlConfig, dataId=DSMALL as connection config
new Dql("DSMALL").id("yyy").execute();

Read eql from diamond

In the connection config, set sql.resource.loader to org.n3r.eql.diamond.DiamondEqlResourceLoader.

package org.n3r.eql;

public class DiamondTest {
    @Test
    public void test1() throws InterruptedException {
        // Will read diamond content of group=EQL,dataId=org.n3r.eql.DiamondTest.eql
        // The diamond content can have the same structure with normal eql file.
        String str = new Eql("diamond").selectFirst("diamondDemo").execute();
        System.out.println(str);
    }
}

Caching sql query result

Sql query result caching can be enabled with cache keyword in sql options:

-- [test1 cache]
SELECT TO_CHAR(SYSTIMESTAMP, 'HH24:MI:SS.FF6') FROM DUAL

The default cache model is based on guava cache with 1 day expired after write.

If you want to use an alternative cache model, you can use write like following:

-- global settings [email protected]("expireAfterWrite=3s,maximumSize=1000")

-- [test1 cache cacheModel=myCache]
SELECT TO_CHAR(SYSTIMESTAMP, 'HH24:MI:SS.FF6') FROM DUAL

The class org.n3r.eql.cache.GuavaCacheProvider is provided by eql and its cache builder spec is same to guava cache spec. Custom cache provider class should implement org.n3r.eql.cache.EqlCacheProvider and optionally to implement org.n3r.eql.spec.ParamsAppliable when there are parameters to set.

simple POJO-based CRUD supported

@EqlTable

To specify the table name related to the class. If class is not annotated by @EqlTable, the default table name will be underscore_lowercase converted from CamelClass name. eg. Person to person, PersonInfo to person_info.

@EqlId

To specify whether the field is a Primary Key in the table. If the property name is id, it is also regarded as implicit @EqlId.

@EqlColumn

To specify the column name which is different with POJO's property name. When non-annotated with @EqlColumn, the default column name will be underscore_lowercase converted from propertyName. eg. name to name, personName to person_name.

@EqlSkip

To skip the mapping to table field.

CRUD

the update and delete api will use the id field as its condition. the read api will use all the non-null fields as its combined condition.

@EqlTable(name = "personx")
public static class Person2 {
    @EqlId
    @EqlColumn(name = "id")
    private String pid;
    @EqlColumn(name = "name")
    private String pname;
    private Integer age;

    @EqlSkip
    private String remark;

    // getters and setters
}

@Test
public void testAnnotation() {
    Person2 person = new Person2();
    person.setPid("1002");
    person.setPname("bingoo");
    person.setAge(30);

    // delete from person where id = ?
    new Pql("mysql").delete(person);

    // insert into person(id,name,age) values(?,?,?)
    new Pql("mysql").create(person);

    person.setPname("huang");
    person.setAge(null);
    // update person set age = ? where id = ?
    int effectedRows = new Pql("mysql").update(person);
    assertThat(effectedRows, is(1));

    Person2 queryPerson = new Person2();
    queryPerson.setPid("1002");

    // select id,name,age from person where id = ?
    List<Person2> resultPerson = new Pql("mysql").read(queryPerson);
    assertThat(resultPerson.size(), is(1));

    effectedRows = new Pql("mysql").delete(queryPerson);
    assertThat(effectedRows, is(1));
}

Eqler

In order to simplify the eql api usage, here eqler is introduced. Eqler is an interface wherein the methods is used to execute sql and process results. An Eqler instance is created by EqlerFactory. The following are examples:

package org.n3r.eql.eqler.crud;

import org.n3r.eql.eqler.annotations.EqlerConfig;
import org.n3r.eql.eqler.annotations.Sql;
import org.n3r.eql.eqler.annotations.SqlId;

import java.util.List;
import java.util.Map;

@EqlerConfig("mysql")
public interface StudentEqler {
    void prepareData();

    int addStudent(int studentId, String name, int age);

    @Sql("insert into eql_student values(#studentId#, #name#, #age#)")
    int addStudent(Student student);

    @Sql("insert into eql_student values(#a#, #b#, #c#)")
    int addStudentAnotherWay(@NamedParam("a") int studentId, @NamedParam("b") String name, @NamedParam("c") int age);

    @Sql("select * from eql_student")
    List<Student> queryAllStudents();

    String queryStudentName(int studentId);

    @SqlId("queryStudent")
    Map<String, Object> queryStudentMap(int studentId);

    Student queryStudent(int studentId);
}
--  org/n3r/eql/eqler/crud/StudentEqler.eql

-- [prepareData]
drop table if exists eql_student;
create table eql_student(student_id int, name varchar(10), age int);

-- [addStudent]
insert into eql_student
values('##', '##', '##')

-- [queryStudentName]
select name from eql_student where student_id = '##'

-- [queryStudent]
select student_id, name, age from eql_student where student_id = '##'
@Test
public void test() {
    StudentEqler eqler = EqlerFactory.getEqler(StudentEqler.class);
    eqler.prepareData();

    eqler.addStudent(1, "bingoo", 123);
    eqler.addStudent(new Student(2, "huang", 124));
    eqler.addStudentAnotherWay(3, "dingoo", 125);

    List<Student> students = eqler.queryAllStudents();
    assertThat(students.toString(), is(equalTo(
            "[Student{studentId=1, name='bingoo', age=123}, " +
                    "Student{studentId=2, name='huang', age=124}, " +
                    "Student{studentId=3, name='dingoo', age=125}]"
    )));

    Student student1 = eqler.queryStudent(1);
    assertThat(student1.toString(), is(equalTo("Student{studentId=1, name='bingoo', age=123}")));

    Map<String, Object> student2 = eqler.queryStudentMap(2);
    assertThat(student2.toString(), is(equalTo("{age=124, name=huang, student_id=2}")));

    String studentName = eqler.queryStudentName(1);
    assertThat(studentName, is(equalTo("bingoo")));
}

TODO

  • Inline comment such as /* iff ... */ is parsed by regular expression, and this method will not ignore /* ... */ in the literal string such as 'literal string /* if xxx */'.

FAQ

MySQLNonTransientConnectionException

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Communications link failure during rollback(). Transaction resolution unknown.
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at com.mysql.jdbc.Util.handleNewInstance(Util.java:377)
	at com.mysql.jdbc.Util.getInstance(Util.java:360)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:935)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:924)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:870)
	at com.mysql.jdbc.ConnectionImpl.rollback(ConnectionImpl.java:4606)
	at org.n3r.eql.trans.SimpleDataSource.popConnection(SimpleDataSource.java:638)
	at org.n3r.eql.trans.SimpleDataSource.getConnection(SimpleDataSource.java:207)
	at org.n3r.eql.trans.EqlSimpleConnection.getConnection(EqlSimpleConnection.java:17)
	at org.n3r.eql.trans.EqlJdbcTran.getConn(EqlJdbcTran.java:58)
	at org.n3r.eql.Eql.createConn(Eql.java:105)
	at org.n3r.eql.Eql.execute(Eql.java:157)

Try use url like jdbc:mysql://127.0.0.1:13306/dba?useUnicode=true&&characterEncoding=UTF-8&connectTimeout=3000&socketTimeout=3000&autoReconnect=true instead of jdbc:mysql://127.0.0.1:13306/dba

FAQ

java.lang.NullPointerException

A single primitive return type like int/long/short will cause NPE when SQL results no rows. In this situation, the related wrapper type like Integer/Long/Short should be used instead.

@Test
public void returnInteger() {
    Integer intValue = new Eql("h2").limit(1)
            .returnType(Integer.class).execute("select 1 where 2 > 3");
    assertThat(intValue).isNull();
}

@Test(expected = NullPointerException.class)
public void returnInt() {
    int intValue = new Eql("h2").limit(1)
            .returnType(int.class).execute("select 1 where 2 > 3");
}

IDEA plugin

eql-plugin

docker

MySQL

  1. docker pull mysql:5.6
  2. docker run -p 13306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.6
  3. mysql -uroot -pmy-secret-pw -h127.0.0.1 -P13306 或者进入容器 docker exec -it mysql bash, 执行mysql -uroot -pmy-secret-pw
  4. create database dba;
    create database dbb;
    create database dbc;

ORACLE

  1. docker pull wnameless/oracle-xe-11g
  2. docker run -d -p 49160:22 -p 49161:1521 -e ORACLE_ALLOW_REMOTE=true wnameless/oracle-xe-11g
  3. download oracle jdbc from oracle website
  4. mvn install:install-file -Dfile=ojdbc6.jar -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0.4.0 -Dpackaging=jar Connect database with following setting:
hostname: localhost
port: 49161
sid: xe
username: system
password: oracle
Password for SYS & SYSTEM

Login by SSH
ssh root@localhost -p 49160
password: admin
Support custom DB Initialization

OGNL 相关知识

eql默认使用OGNL表达式来做动态条件SQL的判断,OGNL表达式可以参见ognl language guide.

注意项

'a' 表示单个字符a,要表示字符串a,需要使用双引号"a"; 'ab'"ab"" 都可以表示字符串ab。

OGNL has the following kinds of constants:

  1. String literals, as in Java (with the addition of single quotes): delimited by single- or double-quotes, with the full set of character escapes;
  2. Character literals, also as in Java: delimited by single-quotes, also with the full set of escapes;
  3. Numeric literals, with a few more kinds than Java. In addition to Java's ints, longs, floats and doubles, OGNL lets you specify BigDecimals with a "b" or "B" suffix, and BigIntegers with an "h" or "H" suffix (think "huge"---we chose "h" for BigIntegers because it does not interfere with hexadecimal digits);
  4. Boolean (true and false) literals;
  5. The null literal.

If you want to compare variable with string in dynamic sql, be careful with single or double quotes.

Testing code:

@SneakyThrows
public static void main(String[] args) {
    val map = ImmutableMap.of(
            "a", "1",
            "b", "11",
            "c", 0,
            "d", "0");
    out.println(Ognl.getValue("a == '1'", map)); // false
    out.println(Ognl.getValue("a == 1", map)); // true
    out.println(Ognl.getValue("a == \"1\"", map)); // true

    out.println(Ognl.getValue("b == '11'", map)); // true
    out.println(Ognl.getValue("b == 11", map)); // true

    out.println(Ognl.getValue("c == \"0\"", map)); // true
    out.println(Ognl.getValue("c == '0'", map)); // false
    out.println(Ognl.getValue("c == 0", map)); // true

    out.println(Ognl.getValue("d == \"0\"", map)); // true
    out.println(Ognl.getValue("d == '0'", map)); // false
    out.println(Ognl.getValue("d == 0", map)); // true
}

More Repositories

1

blog

write blogs with issues
153
star
2

patchca

Simple yet powerful CAPTCHA library written in Java. Original source at http://code.google.com/p/patchca/
Java
44
star
3

idworker-client

client of idworker
Java
37
star
4

quartz-glass

a simple web ui for quartz and jobs simple definition on spring
Java
29
star
5

xlsx

golang mapping between xlsx and struct instances by tag declarations.
Go
28
star
6

diamond-miner

a simple, reliable and easy-to-use java config system base on taobao diamond
Java
22
star
7

redisweb

redis web admin based on go lang
JavaScript
20
star
8

idworker

an ID generator with un-coordinated, under 64-bits, k-sorted, and deterministically unique
Java
19
star
9

excel2javabeans

convert excel rows to javabeans and vice visa
Java
18
star
10

sqlweb

SQL web based on golang
JavaScript
16
star
11

spring-rest-client

spring rest client
Java
14
star
12

delayqueue

delay queue based on redis
Java
12
star
13

westjson

JSON minified without extra format like double quote
Java
12
star
14

gossh

execute shell scripts among multiple ssh servers
Go
12
star
15

buka

a rewrite of kafka in java
Java
12
star
16

westcache

Java annotation based cache, with convenience for cache flush
Java
11
star
17

gostarter

build a starter project for golang, including log, config, ctl, and etc.
Go
10
star
18

weekly

weekly
9
star
19

hbasedao

java dao for hbaes
Java
8
star
20

sqlx

more about golang db sql
Go
7
star
21

golog

log rotate
Go
6
star
22

go-dbsync

synchronize the database tables
Go
6
star
23

pump

pump random data into tables
Go
6
star
24

ec-sshe

an easy java tool for batch operations on multiple ssh remote hosts
Java
5
star
25

berf

perf framework
Go
5
star
26

westid

distributed ID generator
Java
5
star
27

go-devops

devops based on go
Go
5
star
28

asmvalidator

bean validator based on asm
Java
5
star
29

nginx-image-serving

upload and resize image service with nginx
Lua
5
star
30

mysql-cluster

mysql cluster setup tutorial
Go
5
star
31

design-patterns

practise of design patterns
Java
4
star
32

gobench

HTTP upload server benchmark in few languages/frameworks and gobench tool
Go
4
star
33

go-qylogin

wx qiye login
Go
4
star
34

diamond-client

config client of diamond
Java
4
star
35

logtail

tail log and do something
Go
4
star
36

java-utils

java utilities
Java
3
star
37

jj

Go
3
star
38

golang-training-sqlweb

an easy sql web for golang training
Go
3
star
39

gg-rand

generate random data like name, email, uuid, address, images and etc.
Go
3
star
40

braft

Go
2
star
41

labeldb

Go
2
star
42

mallip

ip address maintenence
2
star
43

gou

go utilities
Go
2
star
44

gonet

net relative like port, http, rest
Go
2
star
45

pdf-stripper

strip structured info from pdf
Java
2
star
46

ngx_http_lookup_module

lookup value in ranges
C
2
star
47

Mr.Hbaser

HBase JAVA GUI
Java
2
star
48

cleancode-args

my args program implementation from book "clean code"
Java
2
star
49

avrodemo

all avro demo collected
Java
2
star
50

netgraph

Go
2
star
51

multi-tenants-connection-pool

java connection pool for multi-tenants/databases
Java
2
star
52

gogo

gogo to generate a golang project based on go-starter
Go
2
star
53

javacode-demo

some demo code
Java
2
star
54

Go-JWT-Postgres-Mysql-Restful-API

This is a demo application build with golang, jwt, gorm, postgresql, mysql
Go
2
star
55

settingbean-orm

setting javabean automatic mapping to database setting table
Java
2
star
56

sysinfo

a command to show the system info as full as possible
Go
2
star
57

sql-trigger

jdbc sql trigger to catch crud for specified table or fields
Java
1
star
58

typhon4g

typhon/apollo client for golang
Go
1
star
59

aliyun-mini-api

aliyun minimalism java rest api
Java
1
star
60

logfile

write log from other systems to different files
Go
1
star
61

healthcheck

healthcheck cli for tcp, http and etc.
Go
1
star
62

goreplay-1.1.0

Go
1
star
63

nginx4mall

nginx modifications for mall
C
1
star
64

gotrial

golang 试验田
Go
1
star
65

fastrest

fast restful framework for golang.
Go
1
star
66

goip

show host IP addresses
Go
1
star
67

voucher-no

voucher no generaor
Java
1
star
68

ref

reference
Shell
1
star
69

agiledesktop

敏捷开发者桌面
1
star
70

httplog

httplog
Go
1
star
71

goguide

1
star
72

goxls

go xls
Go
1
star
73

tannangquwu

三国演义·第四二回:我向曾闻云长言,翼德于百万军中,取上将之首,如探囊取物。
Go
1
star
74

devenv

some wikis for development enviroment
1
star
75

codeless

some cases to show how to code less or code none
1
star
76

saas-utils

some utilities for saas
Java
1
star
77

longlived-grpc

Go
1
star
78

gg

golang big and greater
Go
1
star
79

httptee

A reverse HTTP proxy that duplicates requests.
Go
1
star
80

elasticproxy

Go
1
star
81

pngdemo

Java
1
star
82

ngxtpl

golang nginx template
Go
1
star
83

diamond-sdk

sdk of diamond
Java
1
star
84

logmask

mask sensitive in the log
Java
1
star
85

hraftd

hraftd is a reference example use of the Hashicorp Raft
Go
1
star
86

haproxy-config-examples

haproxy configuration examples
Java
1
star
87

now

time and time again for time
Go
1
star
88

logback-more-appenders

more appenders for logback
Java
1
star
89

blackcat-agent

agent that monitor a machine's memory, cpu, processes and etc.
Java
1
star
90

lua

lua learning
Lua
1
star
91

gogotcha

golang gotcha
HTML
1
star
92

blackcat-sdk

sdk for blackcat
Java
1
star
93

spring-rest-boot

rest on spring boot
Java
1
star
94

stonegold-secretdb

a demonstration for auto encryption/decryption of db table secret fields in internal training of touch-a-stone-and-turn-it-into-gold
Java
1
star
95

refactor-cases

code cases for refactoring demo
Java
1
star
96

x-notify

notify by weixin template message, sms and etc.
Java
1
star
97

spring-redis-cache

redis-based cache for spring
Java
1
star
98

go-yoga-tools

yoga-system tools
CSS
1
star
99

filetemplate

provide http and cli api for config file overwrite and reload
Go
1
star
100

pagestatic

utility to retrieve content of remote web pages and rsync to multiple hosts
Java
1
star