/*
* 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.
*/
package org.jdbi.v3.sqlobject;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import org.jdbi.v3.core.Handle;
import org.jdbi.v3.core.ValueType;
import org.jdbi.v3.core.mapper.ValueTypeMapper;
import org.jdbi.v3.core.mapper.reflect.BeanMapper;
import org.jdbi.v3.core.rule.H2DatabaseRule;
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
import org.jdbi.v3.sqlobject.config.RegisterColumnMapper;
import org.jdbi.v3.sqlobject.customizer.BindBean;
import org.jdbi.v3.sqlobject.statement.SqlBatch;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
public class TestBeanMapper
{
@Rule
public H2DatabaseRule dbRule = new H2DatabaseRule().withPlugin(new SqlObjectPlugin());
public static class TestBean
{
private ValueType valueType;
public ValueType getValueType() {
return valueType;
}
public void setValueType(ValueType valueType) {
this.valueType = valueType;
}
}
@RegisterColumnMapper(ValueTypeMapper.class)
public interface TestDao
{
@SqlQuery("select * from testBean")
@RegisterBeanMapper(TestBean.class)
List<TestBean> listBeans();
@SqlQuery("select valueType as bean_value_type from testBean")
@RegisterBeanMapper(value=TestBean.class, prefix="bean_")
List<TestBean> listBeansPrefix();
}
Handle h;
TestDao dao;
@Before
public void createTable() throws Exception {
h = dbRule.openHandle();
h.createUpdate("create table testBean (valueType varchar(50))").execute();
dao = h.attach(TestDao.class);
}
@Test
public void testMapBean() {
h.createUpdate("insert into testBean (valueType) values ('foo')").execute();
List<TestBean> beans = dao.listBeans();
assertThat(beans).extracting(TestBean::getValueType).containsExactly(ValueType.valueOf("foo"));
}
@Test
public void testMapBeanPrefix() {
h.createUpdate("insert into testBean (valueType) values ('foo')").execute();
List<TestBean> beans = dao.listBeansPrefix();
assertThat(beans).extracting(TestBean::getValueType).containsExactly(ValueType.valueOf("foo"));
}
public static class Document {
private int id;
private String name;
private String contents;
public Document() {}
public Document(int id, String name, String contents) {
this.id = id;
this.name = name;
this.contents = contents;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContents() {
return contents;
}
public void setContents(String contents) {
this.contents = contents;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Document)) {
return false;
}
Document that = (Document) obj;
return this.id == that.id &&
Objects.equals(this.name, that.name) &&
Objects.equals(this.contents, that.contents);
}
@Override
public int hashCode() {
return Objects.hash(id, name, contents);
}
}
public static class Folder {
private int id;
private String name;
private List<Document> documents = new ArrayList<>();
public Folder() {}
public Folder(int id, String name, Document... documents) {
this.id = id;
this.name = name;
this.documents = Arrays.asList(documents);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Document> getDocuments() {
return documents;
}
public void setDocuments(List<Document> documents) {
this.documents = documents;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Folder)) {
return false;
}
Folder that = (Folder) obj;
return this.id == that.id &&
Objects.equals(this.name, that.name) &&
Objects.equals(this.documents, that.documents);
}
@Override
public int hashCode() {
return Objects.hash(id, name, documents);
}
}
public interface DocumentDao extends SqlObject {
@SqlBatch("insert into folders (id, name) values (:id, :name)")
void insertFolders(@BindBean Folder... folders);
@SqlBatch("insert into documents (id, folder_id, name, contents) values (:d.id, :f.id, :d.name, :d.contents)")
void insertDocuments(@BindBean("f") Folder folder, @BindBean("d") Document... documents);
default Optional<Folder> getFolder(int folderId) {
return getHandle().createQuery(
"select f.id f_id, f.name f_name, " +
"d.id d_id, d.name d_name, d.contents d_contents " +
"from folders f left join documents d " +
"on f.id = d.folder_id " +
"where f.id = :folderId")
.bind("folderId", folderId)
.registerRowMapper(BeanMapper.factory(Folder.class, "f_"))
.registerRowMapper(BeanMapper.factory(Document.class, "d_"))
.reduceRows(Optional.<Folder>empty(), (folder, row) -> {
Folder f = folder.orElseGet(() -> row.getRow(Folder.class));
if (row.getColumn("d_id", Integer.class) != null) {
f.getDocuments().add(row.getRow(Document.class));
}
return Optional.of(f);
});
}
}
@Test
public void testFoldWithPrefixedMappers() {
h.execute("create table folders (id identity primary key, name varchar(50))");
h.execute("create table documents (id identity primary key, folder_id integer, name varchar(50), contents varchar(1000))");
Folder folder1 = new Folder(1, "folder1");
Folder folder2 = new Folder(2, "folder2");
Folder folder3 = new Folder(3, "folder3");
Document doc1 = new Document(4, "doc1.txt", "hello");
Document doc2 = new Document(5, "doc2.txt", "foo");
Document doc3 = new Document(6, "doc3.txt", "bar");
DocumentDao dao = h.attach(DocumentDao.class);
dao.insertFolders(folder1, folder2, folder3);
dao.insertDocuments(folder2, doc1);
dao.insertDocuments(folder3, doc2, doc3);
assertThat(dao.getFolder(1)).contains(new Folder(1, "folder1"));
assertThat(dao.getFolder(2)).contains(new Folder(2, "folder2", doc1));
assertThat(dao.getFolder(3)).contains(new Folder(3, "folder3", doc2, doc3));
}
}