jutil-sql-log-example

Java Utilities

License

License

GroupId

GroupId

com.github.chrisgleissner
ArtifactId

ArtifactId

jutil-sql-log-example
Last Version

Last Version

1.1.11
Release Date

Release Date

Type

Type

jar
Description

Description

jutil-sql-log-example
Java Utilities
Project Organization

Project Organization

Pivotal Software, Inc.

Download jutil-sql-log-example

How to add to project

<!-- https://jarcasting.com/artifacts/com.github.chrisgleissner/jutil-sql-log-example/ -->
<dependency>
    <groupId>com.github.chrisgleissner</groupId>
    <artifactId>jutil-sql-log-example</artifactId>
    <version>1.1.11</version>
</dependency>
// https://jarcasting.com/artifacts/com.github.chrisgleissner/jutil-sql-log-example/
implementation 'com.github.chrisgleissner:jutil-sql-log-example:1.1.11'
// https://jarcasting.com/artifacts/com.github.chrisgleissner/jutil-sql-log-example/
implementation ("com.github.chrisgleissner:jutil-sql-log-example:1.1.11")
'com.github.chrisgleissner:jutil-sql-log-example:jar:1.1.11'
<dependency org="com.github.chrisgleissner" name="jutil-sql-log-example" rev="1.1.11">
  <artifact name="jutil-sql-log-example" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.github.chrisgleissner', module='jutil-sql-log-example', version='1.1.11')
)
libraryDependencies += "com.github.chrisgleissner" % "jutil-sql-log-example" % "1.1.11"
[com.github.chrisgleissner/jutil-sql-log-example "1.1.11"]

Dependencies

compile (2)

Group / Artifact Type Version
com.github.chrisgleissner : jutil-sql-log jar 1.1.11
org.springframework.boot : spring-boot-starter jar 2.3.0.RELEASE

provided (1)

Group / Artifact Type Version
org.projectlombok : lombok jar 1.18.12

test (4)

Group / Artifact Type Version
org.springframework.boot : spring-boot-starter-test jar 2.3.0.RELEASE
org.springframework.boot : spring-boot-starter-jdbc jar 2.3.0.RELEASE
com.h2database : h2 jar 1.4.200
org.assertj : assertj-core jar 3.16.1

Project Modules

There are no modules declared in this project.

jutil

Maven Central Build Status Coverage Status Maintainability

Java utilities for Protobuf message partitioning, table pretty printing and SQL execution recording.

Features:

  • Partitioning of Protobuf messages to remain below a configurable data size.
  • JDBI column name remapping
  • Pretty-printing of tables with many customization options and adapters for both CSV frameworks and DB ResultSets.
  • Record all SQL executions sent via the DataSources in your Spring Boot application, either in memory or to disk.

Installation

The utilities are packaged in several modules and require at least JDK 8. They are automatically built and tested using OpenJDK 8 and 11.

To use them, simply declare a dependency towards the module you are interested in:

Maven

<dependency>
    <groupId>com.github.chrisgleissner</groupId>
    <artifactId>jutil-protobuf</artifactId>
    <version>1.1.11</version>
</dependency>
<dependency>
    <groupId>com.github.chrisgleissner</groupId>
    <artifactId>jutil-sql-log</artifactId>
    <version>1.1.11</version>
</dependency>
<dependency>
    <groupId>com.github.chrisgleissner</groupId>
    <artifactId>jutil-table</artifactId>
    <version>1.1.11</version>
</dependency>

Gradle

compile 'com.github.chrisgleissner:jutil-protobuf:1.1.11'
compile 'com.github.chrisgleissner:jutil-sql-log:1.1.11'
compile 'com.github.chrisgleissner:jutil-table:1.1.11'

Protobuf Utilities

Javadocs

The ProtobufFieldPartitioner is useful for distributing the elements of a repeated field in a Protobuf message over multiple newly created messages.

This allows for sending a Protobuf message where size restrictions exist, for example when using the Azure Message ServiceBus.

Example:

Collection<Message> msgs = ProtobufFieldPartitioner.partition(msg, repeatedFieldToBePartitioned, 100);

Sql Log

Javadocs

The SqlLog records JSON-formatted SQL executions either in memory or to a file. It gets wired by using Spring Boot 2.3.x auto-configuration and relies on net.ttddyy:datasource-proxy for proxying data sources.

To use this feature, declare a dependency on com.github.chrisgleissner:jutil-sql-log.

Start and Stop

To start recording, wire in the SqlLog bean and call startRecording which returns a SqlRecording. You will now record all SQL messages sent via any DataSource bean as part of your current thread or any thread which it starts.

The recording is kept either on heap (accessible via sqlRecording.getMessages and various methods in SqlLog) or written to the specified file. All SQL is JSON encoded.

Call sqlLog.stopRecording(id) or close a SqlRecording instance to stop its recording.

Default Recording

Any SQL message not recorded otherwise is captured by a default recording which you can get via sqlLog.getDefaultRecording().

This default recording can't be stopped, but you can temporarily stop all recording (including for the default recording) by calling sqlLog.setEnabled(false).

Example

As per ExampleTest, after wiring

@Configuration
public class SampleConfig {
    SampleConfig(JdbcTemplate jdbcTemplate, SqlLog sqlLog) {
        try (SqlRecording rec = sqlLog.startRecording("example", new File("sql.json"), Charset.forName("UTF-8"))) {
            jdbcTemplate.execute("create table foo (id int)");
            jdbcTemplate.execute("insert into foo (id) values (1)");
        }
    }
}

you will find that the sql.json file contains

[{"success":true, "type":"Statement", "batch":false, "querySize":1, "batchSize":0, "query":["create table foo (id int)"], "params":[]},
{"success":true, "type":"Statement", "batch":false, "querySize":1, "batchSize":0, "query":["insert into foo (id) values (1)"], "params":[]}]

JDBI Column Name Mapping

The JDBI Column Mapper allows for easy mapping of a ResultSet into Java objects. The jdbi utility package in this repository provides a wrapper for remapping the column names exposed by a JDBC ResultSet and can thus decorate any ColumnMapper implementation.

This is useful if the DB schema uses a different language or terminology than the Java model to which it is mapped and it is an alternative to applying this mapping via SQL query column labels.

Example:

jdbiHandle.registerRowMapper(RenamingRowMapperFactory.mapColNames(
        ConstructorMapper.factory(Person.class),
        new CsvColumnNameMapping(Path.of("columnNameMappings.csv"))));
List<Person> personList = jdbiHandle.createQuery("select id, nachname, geburtstag from person")
        .mapTo(Person.class)
        .collect(Collectors.toList());

Table Printer

Javadocs

The TablePrinter serializes a table to a pretty-printed string, either using ASCII or UTF borders.

A table consists of a header and a random number of rows. These can can be specified as an Iterable<String> header and Iterable<Iterable<String>> rows. Adapters to various 3rd party frameworks are available, see below.

Example:

Iterable<String> headers = Arrays.asList("firstName", "lastName");
Iterable<Iterable<String>> rows = Arrays.asList(Arrays.asList("john", "doe"), Arrays.asList("joe", "doe"));
System.out.println(DefaultTablePrinter.print(headers, rows));

results in:

+===========+==========+
| firstName | lastName |
|===========|==========|
| john      | doe      |
| joe       | doe      |
+===========+==========+

Alternatively, you can also print to an OutputStream.

Configuration

The TablePrinter is fully configurable to customize your output:

Iterable<String> headers = Arrays.asList("firstName", "lastName");
Iterable<Iterable<String>> rows = Arrays.asList(
        Arrays.asList("Tom", "Selleck"), 
        Arrays.asList("John", "Hillerman"),
        Arrays.asList("Roger E.", null), 
        Arrays.asList("Larry", "Manetti"));

System.out.println(TablePrinter.builder()
        .horizontalDividers(true)
        .nullValue("n/a")
        .tableFormat(new Utf8TableFormat())
        .rowNumbers(true)
        .startRow(1)
        .endRow(3)
        .maxCellWidth(5)
        .wraparound(false)
        .build().print(headers, rows));

results in:

╔═══╤═══════╤═══════╗
║ # │ first │ lastN ║
╠═══╪═══════╪═══════╣
║ 1 │ John  │ Hille ║
╟───┼───────┼───────╢
║ 2 │ Roger │ n/a   ║
╟───┼───────┼───────╢
║ 3 │ Larry │ Manet ║
╚═══╧═══════╧═══════╝

As per the example above, if you have a very large data structure, you may want to use the startRow and endRow builder methods to only print the specified range. You can also set the maximum cell width (defaults to 100) and control the wrap-aroud of long cells (enabled by default).

Newlines are supported and tabs are rendered as 8 spaces (configurable).

3rd Party Adapters

Any data structure that implements the TableProvider interface can be printed and various adapters for this interface are available:

DB ResultSet

Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:mem:test", "sa", "");
String s = DefaultTablePrinter.print(
        new ResultSetTableProvider(conn.createStatement().executeQuery("select * from foo"))));

Univocity CSV Parser

CsvParserSettings settings = new CsvParserSettings();
settings.setHeaderExtractionEnabled(true);
CsvParser parser = new CsvParser(settings);
String s = DefaultTablePrinter.print(
        UnivocityTableProvider.of(parser.iterateRecords(new File("sample.csv"))));

Apache Commons CSV Parser

String s = DefaultTablePrinter.print(
    new ApacheCsvTableProvider(CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(
        new FileReader(new File("sample.csv")))))
                

JavaBeans

Iterable<Person> people = Arrays.asList(new Person("john", "doe", 30),
        new Person("mary", "poppins", 40));
String s = DefaultTablePrinter.print(new BeanTableProvider(people))             

Versions

Version
1.1.11
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5