Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
java: [11, 17, 19, 20-ea]
java: [11, 17, 20, 21-ea]
distribution: ['zulu']
fail-fast: false
max-parallel: 5
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ public static QueryExpressionDSL.FromGatherer<SelectModel> selectDistinct(BasicC
return selectDistinct(Function.identity(), selectList);
}

public static QueryExpressionDSL.FromGatherer<SelectModel> selectDistinct(Collection<? extends BasicColumn> selectList) {
public static QueryExpressionDSL.FromGatherer<SelectModel> selectDistinct(
Collection<? extends BasicColumn> selectList) {
return selectDistinct(Function.identity(), selectList);
}

Expand Down
4 changes: 2 additions & 2 deletions src/site/markdown/docs/codingStandards.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ these general principles for functional style coding in Java:

We are committed to clean code. This means:

- Small methods - less than 5 lines is good, 1 line is ideal
- Small methods - less than 5 lines is good, 1 line is ideal
- Small classes - less than 100 lines is good, less than 50 lines is ideal
- Use descriptive names
- Comments are a last resort - don't comment bad code, refactor it
Expand All @@ -43,7 +43,7 @@ We are committed to clean code. This means:
Remember the three rules of TDD:

1. You may not write production code until you have written a failing unit test.
2. You may not write more of a unit test than is sufficient to fail, and not compiling is failing.
2. You may not write more of a unit test than is sufficient to fail, and not compiling is failing.
3. You may not write more production code than is sufficient to passing the currently failing test.


6 changes: 3 additions & 3 deletions src/site/markdown/docs/complexQueries.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public SelectStatementProvider search(Integer targetId, String fName, String lNa
var builder = select(id, firstName, lastName) // (1)
.from(person)
.where(); // (2)

if (targetId != null) { // (3)
builder
.and(id, isEqualTo(targetId));
Expand All @@ -32,10 +32,10 @@ public SelectStatementProvider search(Integer targetId, String fName, String lNa
builder
.orderBy(lastName, firstName)
.fetchFirst(50).rowsOnly(); // (7)

return builder.build().render(RenderingStrategies.MYBATIS3); // (8)
}

public String addWildcards(String s) {
return "%" + s + "%";
}
Expand Down
10 changes: 5 additions & 5 deletions src/site/markdown/docs/conditions.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ List<Animal> search(String searchName) {
.orderBy(id)
.build()
.render(RenderingStrategies.MYBATIS3);

...
}
```
Expand All @@ -97,7 +97,7 @@ List<Animal> search(String searchName){
.build()
.render(RenderingStrategies.MYBATIS3);
}

String appendWildCards(String in) {
return "%" + in + "%";
}
Expand Down Expand Up @@ -144,7 +144,7 @@ If all three values are null, then no where clause will be generated.
Each of the conditions accepts a lambda expression that can be used to determine if the condition should render or not.
The lambdas will all be of standard JDK types (either `java.util.function.BooleanSupplier`,
`java.util.function.Predicate`, or `java.util.function.BiPredicate` depending on the type of condition). The following
table lists the optional conditions and shows how to use them:
table lists the optional conditions and shows how to use them:

| Condition | Example | Rendering Rules |
|-----------|---------|-----------------|
Expand Down Expand Up @@ -197,7 +197,7 @@ Optionality with the "in" and "not in" conditions is a bit more complex than the
thing to know is that no "in" or "not in" condition will render if the list of values is empty. For example, there
will never be rendered SQL like `where name in ()`. So optionality of the "in" conditions is more about optionality
of the *values* of the condition. The library comes with functions that will filter out null values, and will upper
case String values to enable case insensitive queries. There are extension points to add additional filtering and
case String values to enable case insensitive queries. There are extension points to add additional filtering and
mapping if you so desire.

The following table shows the different supplied In conditions and how they will render for different sets of inputs.
Expand All @@ -218,7 +218,7 @@ The table assumes the following types of input:
| IsNotInCaseInsensitive | No | Yes | upper(name) not in ('FOO', null, 'BAR') | upper(name) not in (null) |
| IsNotInCaseInsensitiveWhenPresent | Yes | Yes | upper(name) not in ('FOO', 'BAR') | No Render |

If none of these options meet your needs, the "In" conditions also support "map" and "filter" methods for the values.
If none of these options meet your needs, the "In" conditions also support "map" and "filter" methods for the values.
This gives you great flexibility to alter or filter the value list before the condition
is rendered.

Expand Down
4 changes: 2 additions & 2 deletions src/site/markdown/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ The configuration file is a standard Java properties file. The possible values a
## Statement Configuration

If the global configuration is not acceptable for any individual statement, you can also configure the statement in the
DSL. Consider the following statement:
DSL. Consider the following statement:

```java
DeleteStatementProvider deleteStatement = deleteFrom(animalData)
Expand All @@ -52,7 +52,7 @@ The Kotlin DSL contains the same function:
```kotlin
val deleteStatement = deleteFrom(person) {
where { id isEqualToWhenPresent null }
configureStatement { isNonRenderingWhereClauseAllowed = true }
configureStatement { isNonRenderingWhereClauseAllowed = true }
}
```

6 changes: 3 additions & 3 deletions src/site/markdown/docs/delete.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ For example:
DeleteStatementProvider deleteStatement = deleteFrom(foo)
.build()
.render(RenderingStrategies.MYBATIS3);
```
```

## Annotated Mapper for Delete Statements

The DeleteStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you
are using an annotated mapper, the delete method should look like this:

```java
import org.apache.ibatis.annotations.DeleteProvider;
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
Expand All @@ -41,7 +41,7 @@ We do not recommend using an XML mapper for delete statements, but if you want t
object can be used as a parameter to a MyBatis mapper method directly.

If you are using an XML mapper, the delete method should look like this in the Java interface:

```java
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;

Expand Down
2 changes: 1 addition & 1 deletion src/site/markdown/docs/exceptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ All of these exceptions can be avoided through proper use of the DSL and validat
Most conditions in a where clause provide optionality - they have `filter` methods that can cause the condition to be
dropped from the where clause. If all the conditions in a where clause fail to render, then the where clause itself is
dropped from the rendered SQL. This can be dangerous in that it can cause a statement to be generated that affects all
rows in a table. For example, all rows could be deleted. As of version 1.4.1, the library will throw a
rows in a table. For example, all rows could be deleted. As of version 1.4.1, the library will throw a
`NonRenderingWhereClauseException` in this case out of an abundance of caution. This behavior can be overridden
through either global configuration, or by configuring individual statements to allow for where clauses to be dropped.

Expand Down
6 changes: 3 additions & 3 deletions src/site/markdown/docs/extending.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ A calculated column can be used anywhere in a SELECT statement. If you don't ne

```java
public class CountAll implements BasicColumn {

private String alias;

public CountAll() {
Expand Down Expand Up @@ -100,7 +100,7 @@ public class ToBase64 extends AbstractTypeConvertingFunction<byte[], String, ToB
protected ToBase64 copy() {
return new ToBase64(column);
}

public static ToBase64 toBase64(BindableColumn<byte[]> column) {
return new ToBase64(column);
}
Expand All @@ -113,7 +113,7 @@ The following function implements the common database `UPPER()` function.

```java
public class Upper extends AbstractUniTypeFunction<String, Upper> {

private Upper(BindableColumn<String> column) {
super(column);
}
Expand Down
6 changes: 3 additions & 3 deletions src/site/markdown/docs/howItWorks.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ templating engine for generating dynamic SQL.
For example, MyBatis can execute an SQL string formatted like this:

```sql
select id, description from table_codes where id = #{id,jdbcType=INTEGER}
select id, description from table_codes where id = #{id,jdbcType=INTEGER}
```

This is standard SQL with a MyBatis twist - the parameter notation `#{id,jdbcType=INTEGER}`
Expand All @@ -36,11 +36,11 @@ public class Parameter {
public Parameter(Integer id) {
this.id = id;
}

public Integer getId() {
return id;
}

public String getSql() {
return sql;
}
Expand Down
22 changes: 11 additions & 11 deletions src/site/markdown/docs/insert.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ The library will generate a variety of INSERT statements:
1. An insert for multiple rows with a single statement
1. An insert for multiple rows with a JDBC batch
1. A general insert statement
1. An insert with a select statement
1. An insert with a select statement

## Single Row Insert
A single record insert is a statement that inserts a single record into a table. This statement is configured differently than other statements in the library so that MyBatis' support for generated keys will work properly. To use the statement, you must first create an object that will map to the database row, then map object attributes to fields in the database. For example:
Expand Down Expand Up @@ -42,7 +42,7 @@ Notice the `map` method. It is used to map a database column to an attribute of
3. `map(column).toStringConstant(constant_value)` will insert a constant into a column. The constant_value will be written into the generated insert statement surrounded by single quote marks (as an SQL String)
4. `map(column).toProperty(property)` will insert a value from the record into a column. The value of the property will be bound to the SQL statement as a prepared statement parameter
5. `map(column).toPropertyWhenPresent(property, Supplier<?> valueSupplier)` will insert a value from the record into a column if the value is non-null. The value of the property will be bound to the SQL statement as a prepared statement parameter. This is used to generate a "selective" insert as defined in MyBatis Generator.
6. `map(column).toRow()` will insert the record itself into a column. This is appropriate when the "record" is a simple class like Integer or String.
6. `map(column).toRow()` will insert the record itself into a column. This is appropriate when the "record" is a simple class like Integer or String.

### Annotated Mapper for Single Row Insert Statements
The InsertStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you
Expand All @@ -64,7 +64,7 @@ import org.mybatis.dynamic.sql.util.SqlProviderAdapter;
We do not recommend using an XML mapper for insert statements, but if you want to do so the InsertStatementProvider object can be used as a parameter to a MyBatis mapper method directly.

If you are using an XML mapper, the insert method should look like this in the Java interface:

```java
import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider;

Expand Down Expand Up @@ -110,15 +110,15 @@ A multiple row insert statement looks like this:
try (SqlSession session = sqlSessionFactory.openSession()) {
GeneratedAlwaysAnnotatedMapper mapper = session.getMapper(GeneratedAlwaysAnnotatedMapper.class);
List<GeneratedAlwaysRecord> records = getRecordsToInsert(); // not shown

MultiRowInsertStatementProvider<GeneratedAlwaysRecord> multiRowInsert = insertMultiple(records)
.into(generatedAlways)
.map(id).toProperty("id")
.map(firstName).toProperty("firstName")
.map(lastName).toProperty("lastName")
.build()
.render(RenderingStrategies.MYBATIS3);

int rows = mapper.insertMultiple(multiRowInsert);
}
```
Expand All @@ -143,7 +143,7 @@ import org.mybatis.dynamic.sql.util.SqlProviderAdapter;
We do not recommend using an XML mapper for insert statements, but if you want to do so the MultiRowInsertStatementProvider object can be used as a parameter to a MyBatis mapper method directly.

If you are using an XML mapper, the insert method should look like this in the Java interface:

```java
import org.mybatis.dynamic.sql.insert.render.MultiInsertStatementProvider;

Expand Down Expand Up @@ -189,7 +189,7 @@ that we expect generated values. Further, note that the `keyProperty` is set to
return the `insertStatement` as supplied in the method call. The adapter method requires that there be one, and only
one, String parameter in the method call, and it assumes that this one String parameter is the SQL insert statement.
The parameter can have any name and can be specified in any position in the method's parameter list.
The `@Param` annotation is not required for the insert statement. However, it may be specified if you so desire.
The `@Param` annotation is not required for the insert statement. However, it may be specified if you so desire.

The second method above decomposes the `MultiRowInsertStatementProvider` and calls the first method.

Expand Down Expand Up @@ -222,7 +222,7 @@ A batch insert is a collection of statements that can be used to execute a JDBC

It is important to open a MyBatis session by setting the executor type to BATCH. The records are inserted on the commit. You can call commit multiple times if you want to do intermediate commits.

Notice that the same mapper method that is used to insert a single record is now executed multiple times. The `map` methods are the same with the exception that the `toPropertyWhenPresent` mapping is not supported for batch inserts.
Notice that the same mapper method that is used to insert a single record is now executed multiple times. The `map` methods are the same with the exception that the `toPropertyWhenPresent` mapping is not supported for batch inserts.

## General Insert Statement
A general insert is used to build arbitrary insert statements. The general insert does not require a separate record object to hold values for the statement - any value can be passed into the statement. This version of the insert is not convenient for retrieving generated keys with MyBatis - for that use case we recommend the "single record insert". However the general insert is perfectly acceptable for Spring JDBC template or MyBatis inserts that do not return generated keys. For example
Expand Down Expand Up @@ -265,7 +265,7 @@ import org.mybatis.dynamic.sql.util.SqlProviderAdapter;
We do not recommend using an XML mapper for insert statements, but if you want to do so the GeneralInsertStatementProvider object can be used as a parameter to a MyBatis mapper method directly.

If you are using an XML mapper, the insert method should look like this in the Java interface:

```java
import org.mybatis.dynamic.sql.insert.render.GeneralInsertStatementProvider;

Expand Down Expand Up @@ -299,7 +299,7 @@ An insert select is an SQL insert statement the inserts the results of a select

int rows = mapper.insertSelect(insertSelectStatement);
```
The column list is optional and can be removed if the selected columns match the layout of the table.
The column list is optional and can be removed if the selected columns match the layout of the table.

### Annotated Mapper for Insert Select Statements
The InsertSelectStatementProvider object can be used as a parameter to a MyBatis mapper method directly. If you
Expand All @@ -322,7 +322,7 @@ Note that MyBatis does not support overloaded mapper method names, so the name o
We do not recommend using an XML mapper for insert statements, but if you want to do so the InsertSelectStatementProvider object can be used as a parameter to a MyBatis mapper method directly.

If you are using an XML mapper, the insert method should look like this in the Java interface:

```java
import org.mybatis.dynamic.sql.insert.render.InsertSelectStatementProvider;

Expand Down
4 changes: 2 additions & 2 deletions src/site/markdown/docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ The primary goals of the library are:
3. Flexible - where clauses can be built using any combination of and, or, and nested conditions
4. Extensible - the library will render statements for MyBatis3, Spring JDBC templates or plain JDBC.
It can be extended to generate clauses for other frameworks as well. Custom where conditions can
be added easily if none of the built in conditions are sufficient for your needs.
be added easily if none of the built in conditions are sufficient for your needs.
5. Small - the library is a small dependency to add. It has no transitive dependencies.

This library grew out of a desire to create a utility that could be used to improve the code
generated by MyBatis Generator, but the library can be used on its own with very little setup required.
10 changes: 5 additions & 5 deletions src/site/markdown/docs/kotlinMyBatis3.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ The extension methods will reuse the abstract methods and add functionality to m
execute the SQL statements in a one-step process. The extension methods shown below assume that you will create
a set of CRUD methods for each table you are accessing (as is the case with code created by MyBatis Generator).

If you create a Kotlin mapper interface that includes both abstract and non-abstract methods, MyBatis will
If you create a Kotlin mapper interface that includes both abstract and non-abstract methods, MyBatis will
throw errors. By default, Kotlin does not create Java default methods in an interface. For this reason, Kotlin
mapper interfaces should only contain the actual MyBatis mapper abstract interface methods. What would normally be coded
as default or static methods in a Java mapper interface should be coded as extension methods in Kotlin. For example,
Expand Down Expand Up @@ -556,7 +556,7 @@ val rows = mapper.insertMultiple(record1, record2)

### Generated Key Support

Multi-row insert statements support returning a generated key using normal MyBatis generated key support. However,
Multi-row insert statements support returning a generated key using normal MyBatis generated key support. However,
generated keys require some care for multi-row insert statements. In this section we will show how to use the
library's built-in support. When generated keys are expected you must code the mapper method manually and supply the
`@Options` annotation that configures generated key support. You cannot use the built-in base interface when there are
Expand Down Expand Up @@ -606,7 +606,7 @@ import org.apache.ibatis.executor.BatchResult
interface PersonMapper {
@InsertProvider(type = SqlProviderAdapter::class, method = "insert")
fun insert(insertStatement: InsertStatementProvider<PersonRecord>): Int

@Flush
fun flush(): List<BatchResult>
}
Expand Down Expand Up @@ -838,7 +838,7 @@ distinct can be executed with the `selectMany` method.
### One-Step Method
You can use built-in utility functions to create mapper extension functions that simplify execution of select statements.
The extension functions will reuse the abstract methods and supply the table and column list for the statement.
We recommend three extension methods for select multiple records, select multiple records with the distinct keyword,
We recommend three extension methods for select multiple records, select multiple records with the distinct keyword,
and selecting a single record:

```kotlin
Expand Down Expand Up @@ -1024,7 +1024,7 @@ It is also possible to write utility methods that will set values. For example:
fun KotlinUpdateBuilder.updateSelectiveColumns(record: PersonRecord) =
apply {
set(id) equalToWhenPresent record::id
set(firstName) equalToWhenPresent record::firstName
set(firstName) equalToWhenPresent record::firstName
set(lastName) equalToWhenPresent record::lastName
set(birthDate) equalToWhenPresent record::birthDate
set(employed) equalToWhenPresent record::employed
Expand Down
Loading