Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support dynamic indexed access on mb:p tag #42

Merged
merged 1 commit into from
Nov 4, 2019
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
21 changes: 21 additions & 0 deletions src/main/asciidoc/user-guide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,27 @@ SELECT * FROM names
/*[/]*/
ORDER BY id
----

Since 1.0.2, We support the indexed access using an iteration status object as follow:

[source,sql]
.Use indexed access using an iteration status object
----
SELECT * FROM names
WHERE 1 = 1
/*[# th:if="${not #lists.isEmpty(ids)}"]*/
AND id IN (
/*[# th:each="id : ${ids}"]*/
/*[# mb:p="ids[${idStat.index}]"]*/ 1 /*[/]*/ -- <1>
/*[(${idStat.last} ? '' : ',')]*/
/*[/]*/
)
/*[/]*/
ORDER BY id
----

<1> Access to a iterable object using indexed

====

About more advanced usage of `th:each` , please see <<Bulk insert>>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ public MyBatisParamTagProcessor(final TemplateMode templateMode, final String pr
@Override
protected void doProcess(ITemplateContext context, IProcessableElementTag tag, AttributeName attributeName,
String attributeValue, IElementTagStructureHandler structureHandler) {
if (attributeValue.contains("${")) {
attributeValue = getExpressionEvaluatedText(context, tag, attributeName, attributeValue);
}

Pair parameterAndOptionPair = Pair.parse(attributeValue, ',');
String parameterPath = parameterAndOptionPair.left;
String options = parameterAndOptionPair.right;
Expand Down Expand Up @@ -111,6 +115,13 @@ private Object getExpressionEvaluatedValue(ITemplateContext context, IProcessabl
return expression.execute(context, this.expressionExecutionContext);
}

private String getExpressionEvaluatedText(ITemplateContext context, IProcessableElementTag tag,
AttributeName attributeName, String parameterValue) {
IStandardExpression expression = EngineEventUtils.computeAttributeExpression(context, tag, attributeName,
"|" + parameterValue + "|");
return expression.execute(context, this.expressionExecutionContext).toString();
}

private boolean isCollectionOrArray(Object value) {
return value != null && (Collection.class.isAssignableFrom(value.getClass()) || value.getClass().isArray());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -383,11 +383,11 @@ void testBulkInsertAndSelect() {
persons.add(person);
}

int maxMailId = Optional.ofNullable(mapper.getMaxMailId()).filter(x -> x != 0).orElse(-1);

mapper.insertByBulk(persons);
mapper.insertMailsByBulk(persons);

int maxMailId = Optional.ofNullable(mapper.getMaxMailId()).filter(x -> x != 0).orElse(-1) - 4;

// Select
List<Person> loadedPersons = mapper.selectPersons(persons.get(0).getId(), persons.get(1).getId());
Assertions.assertEquals(2, loadedPersons.size());
Expand Down Expand Up @@ -478,4 +478,94 @@ void testBulkInsertAndSelect() {
}
}

@Test
void testBulkInsertWithIndexedAndSelect() {

try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
// Insert
List<Person> persons = new ArrayList<>();
{
Person person = new Person();
person.setName("MyBatis 1");
List<Mail> mails = new ArrayList<>();
person.setMails(mails);
{
Mail mail = new Mail();
mail.setAddress("mybatis1.main@test.com");
mails.add(mail);
}
{
Mail mail = new Mail();
mail.setAddress("mybatis1.sub@test.com");
mails.add(mail);
}
persons.add(person);
}
{
Person person = new Person();
person.setName("MyBatis 2");
List<Mail> mails = new ArrayList<>();
person.setMails(mails);
{
Mail mail = new Mail();
mail.setAddress("mybatis2.main@test.com");
mails.add(mail);
}
{
Mail mail = new Mail();
mail.setAddress("mybatis2.sub@test.com");
mails.add(mail);
}
persons.add(person);
}

mapper.insertByBulkWithIndexed(persons);
mapper.insertMailsByBulkWithIndexed(persons);

int maxMailId = Optional.ofNullable(mapper.getMaxMailId()).filter(x -> x != 0).orElse(-1) - 4;

// Select
List<Person> loadedPersons = mapper.selectPersons(persons.get(0).getId(), persons.get(1).getId());
Assertions.assertEquals(2, loadedPersons.size());
{
Person person = loadedPersons.get(0);
Assertions.assertEquals(persons.get(0).getId(), person.getId());
Assertions.assertEquals("MyBatis 1", person.getName());
List<Mail> mails = person.getMails();
Assertions.assertEquals(2, mails.size());
{
Mail mail = mails.get(0);
Assertions.assertEquals(maxMailId + 1, mail.getId());
Assertions.assertEquals(persons.get(0).getId(), mail.getPersonId());
Assertions.assertEquals("mybatis1.main@test.com", mail.getAddress());
}
{
Mail mail = mails.get(1);
Assertions.assertEquals(maxMailId + 2, mail.getId());
Assertions.assertEquals(persons.get(0).getId(), mail.getPersonId());
Assertions.assertEquals("mybatis1.sub@test.com", mail.getAddress());
}
}
{
Person person = loadedPersons.get(1);
Assertions.assertEquals(persons.get(1).getId(), person.getId());
Assertions.assertEquals("MyBatis 2", person.getName());
List<Mail> mails = person.getMails();
Assertions.assertEquals(2, mails.size());
{
Mail mail = mails.get(0);
Assertions.assertEquals(maxMailId + 3, mail.getId());
Assertions.assertEquals(persons.get(1).getId(), mail.getPersonId());
Assertions.assertEquals("mybatis2.main@test.com", mail.getAddress());
}
{
Mail mail = mails.get(1);
Assertions.assertEquals(maxMailId + 4, mail.getId());
Assertions.assertEquals(persons.get(1).getId(), mail.getPersonId());
Assertions.assertEquals("mybatis2.sub@test.com", mail.getAddress());
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,16 @@ public interface PersonMapper {
@Insert("sql/PersonMapper/insertByBulk.sql")
void insertByBulk(List<Person> persons);

@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("sql/PersonMapper/insertByBulkWithIndexed.sql")
void insertByBulkWithIndexed(List<Person> persons);

@Insert("sql/PersonMapper/insertMailsByBulk.sql")
void insertMailsByBulk(List<Person> persons);

@Insert("sql/PersonMapper/insertMailsByBulkWithIndexed.sql")
void insertMailsByBulkWithIndexed(List<Person> persons);

@Select("SELECT MAX(id) FROM person_mails")
Integer getMaxMailId();

Expand Down
22 changes: 22 additions & 0 deletions src/test/resources/sql/PersonMapper/insertByBulkWithIndexed.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--
-- Copyright 2018-2019 the original author or authors.
--
-- 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.
--

INSERT INTO persons (name) VALUES
/*[# th:each="person : ${list}"]*/
(
/*[# mb:p="list[${personStat.index}].name"]*/ 'Taro Yamada' /*[/]*/
)/*[(${personStat.last} ? '' : ',')]*/
/*[/]*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--
-- Copyright 2018-2019 the original author or authors.
--
-- 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.
--

INSERT INTO person_mails (person_id, address) VALUES
/*[# th:each="person : ${list}"]*/
/*[# th:each="mail : ${person.mails}"]*/
(
/*[# mb:p="list[${personStat.index}].id"]*/ 1 /*[/]*/,
/*[# mb:p="list[${personStat.index}].mails[${mailStat.index}].address"]*/ 'taro.yamada@test.com' /*[/]*/
)/*[(${personStat.last and mailStat.last} ? '' : ',')]*/
/*[/]*/
/*[/]*/