GithubHelp home page GithubHelp logo

jhannes / fluent-jdbc Goto Github PK

View Code? Open in Web Editor NEW
32.0 32.0 3.0 2.12 MB

Java database code without ORM in a pleasant and fluent style

License: Apache License 2.0

Java 100.00%
database fluent java jdbc library

fluent-jdbc's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

fluent-jdbc's Issues

Suggestion: wrap `whereExpression` in parenthesis

Given this code:

public boolean foo(int projectId) {
    return table
        .where("project_id", projectId)
        .whereExpression("entry_id is not null or entry_comment_id is not null")
        .getCount() > 0;
}

The or in the whereExpression can match rows with a different project_id than the one given as an argument.

I was expecting the whereExpression to get wrapped in parenthesis and not interfere with the call to where.

Thoughts?

Support for "fetch first"

It would be nice to have support for standard statement "FETCH FIRST x ROWS ONLY":
according to SQL:2008. That would make the statement below easier to both read and write:

image

Incompatibility with micronaut

I tried to use this library with micronaut, however, after adding the dependency, project doesn't start due to slf4j-api incompatibility.
"Class path contains SLF4J bindings targeting slf4j-api versions prior to 1.8 "
I've tried to exclude slf4j-api from with gradle exclude, but without any success.

Sync-builder which synchronizes a table with an list of objects

Motivating example

table.syncBuilder(collection)
    .unique("keyOne", it -> it.getKeyOne())
    .unique("keyTwo", it -> it.getKeyTwo())
   .field("value1", it -> it.getValueOne())
   .field("value2", it -> it.getValueTwo())
   .cacheExisting()
   .deleteExtras()
   .insertMissing()
   .updateDiffering()
  .execute();

Add support for named parameters and improve sql support

It's useful to be able to add parameters using named fields instead of "?" markers. This reduces confusion around what goes where, better supports duplicated references to same parameter, and avoids having to track posistions or generate lists of "?" for IN clauses etc.

E.g.

return new DbStatement("Select a.* from MyTable a where a.someField=:someField and a.status IN (:status)")
.setField("name", "some value")
.setField("status", List.of("status1", "status2", "status3")
.executeQuery();

Sample code:
`
package org.fluentjdbc;
import java.util.;
import java.util.regex.
;
import java.util.stream.*;
public class DbStatement {

static class Field {
	String name;
	int start;
	int end;

	Field(String name, int start, int end) {
		this.name = name;
		this.start = start;
		this.end = end;
	}

	@Override
	public String toString() {
		return getClass().getSimpleName() + "<" + name + "," + start + "," + end + ">";
	}
}

private static final Pattern FIELD_REGEXP = Pattern.compile("(?:'[^']+')|:([a-zA-Z0-9_]+)");

private final String statement;

/** order of fields in statement. */
private final List<Field> fieldOrder = new ArrayList<>();
private final Map<String, List<?>> fieldParams = new LinkedHashMap<>();

public DbStatement(String stmt) {
	this.statement = Objects.requireNonNull(stmt);
	Matcher m = FIELD_REGEXP.matcher(stmt);
	while (m.find()) {
		if (m.group(1) != null) {
			fieldOrder.add(new Field(m.group(1), m.start(), m.end()));
		}
	}
}

void executeQuery() {
	Set<String> fields = fieldOrder.stream().map(f -> f.name).collect(Collectors.toSet());
	if (!fieldParams.keySet().equals(fields)) {
		throw new IllegalStateException("Forventet : " + fields + ", men har " + fieldParams.keySet());
	}
	StringBuilder sql = new StringBuilder();

	int last = 0;
	for (Field f : fieldOrder) {
		sql.append(statement.subSequence(last, f.start));
		String[] args = new String[fieldParams.get(f.name).size()];
		Arrays.fill(args, "?");
		String qs = String.join(",", Arrays.asList(args));
		sql = sql.append(qs);
		last = f.end;
	}
	sql.append(statement.substring(last));

	int i = 1;
	for (Field f : fieldOrder) {
		for (Object v : fieldParams.get(f.name)) {
			// TODO: populate statement
			System.out.println(i++ + ": " + f.name + " =" + v);
		}
	}

	// TODO: execute
	System.out.println(sql);

}

public void setField(String fieldName, Object val) {
	this.fieldParams.put(fieldName, List.of(val));
}

public void setField(String fieldName, List<Object> vals) {
	fieldParams.put(fieldName, vals);
}

List<Field> getFieldOrder() {
	return Collections.unmodifiableList(fieldOrder);
}

Map<String, List<?>> getFieldParams() {
	return Collections.unmodifiableMap(fieldParams);
}

}

class TestDbStatement {
public static void main(String[] args) {
DbStatement stmt = new DbStatement(
"select * from hello where id=:myField1 and name=':notincluded' and id2 IN(:myField_2) and id3= :myField1");

	System.out.println(stmt.getFieldOrder());

	stmt.setField("myField1", 999);
	stmt.setField("myField_2", List.of("A", "B", "C"));

	stmt.executeQuery();
}

}
`

Add DbContextExtension for junit5

https://github.com/jhannes/fluent-jdbc/blob/main/src/main/java/org/fluentjdbc/opt/junit/DbContextRule.java needs to be converted to something like this:

public class DbContextExtension extends DbContext 
        implements BeforeEachCallback, AfterEachCallback {
    val DbContextConnection ignoredConnection     
    
    // Constructors is bad most likley, need to check how to provide constructor argument to an Extension class. 
    // Maybe allow to set datasource and databaseStatementFactory via setters in a @BeforeClass/@Before  when using the extension? 
    
    
    public DbContextExtension(DataSource dataSource) {
        this(dataSource, new DatabaseStatementFactory(DatabaseReporter.LOGGING_REPORTER));
    }

    public DbContextExtension(DataSource dataSource, DatabaseStatementFactory factory) {
        super(factory);
        this.dataSource = dataSource;
    }

    @Override
    public void beforeEach(ExtensionContext context) throws Exception {
      ignoredConnection = startConnection(dataSource)
    }

    @Override
    public void afterEach(ExtensionContext context) throws Exception {
      if (ignoredConnection != null) ignoredConnection.close()
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.