diff --git a/src/main/java/jp/co/future/uroborosql/SqlEntityQueryImpl.java b/src/main/java/jp/co/future/uroborosql/SqlEntityQueryImpl.java index aaf541eb..03ea675d 100644 --- a/src/main/java/jp/co/future/uroborosql/SqlEntityQueryImpl.java +++ b/src/main/java/jp/co/future/uroborosql/SqlEntityQueryImpl.java @@ -246,6 +246,26 @@ public long count(final String col) { } } + /** + * 数値型のカラムかどうかの判定.
+ * Optional型の場合、OptionalのGenerics型で指定された型が数値型かどうかを判定する. + * + * @param mappingColumn MappingColumn + * @return 数値型のカラムの場合true. + */ + private static boolean isNumberTypeColumn(final MappingColumn mappingColumn) { + Class rawType = mappingColumn.getJavaType().getRawType(); + if (Optional.class.equals(rawType)) { + rawType = mappingColumn.getJavaType().getParam(0).getRawType(); + } + return short.class.equals(rawType) || + int.class.equals(rawType) || + long.class.equals(rawType) || + float.class.equals(rawType) || + double.class.equals(rawType) || + Number.class.isAssignableFrom(rawType); + } + /** * {@inheritDoc} * @@ -256,13 +276,7 @@ public long count(final String col) { public T sum(final String col) { String camelColumnName = CaseFormat.CAMEL_CASE.convert(col); MappingColumn mappingColumn = MappingUtils.getMappingColumn(context().getSchema(), entityType, camelColumnName); - Class rawType = mappingColumn.getJavaType().getRawType(); - if (!(short.class.equals(rawType) || - int.class.equals(rawType) || - long.class.equals(rawType) || - float.class.equals(rawType) || - double.class.equals(rawType) || - Number.class.isAssignableFrom(mappingColumn.getJavaType().getRawType()))) { + if (!isNumberTypeColumn(mappingColumn)) { throw new UroborosqlRuntimeException("Column is not of type Number. col=" + camelColumnName); } TableMetadata.Column column = tableMetadata.getColumn(camelColumnName); diff --git a/src/test/java/jp/co/future/uroborosql/mapping/DefaultEntityHandlerTest.java b/src/test/java/jp/co/future/uroborosql/mapping/DefaultEntityHandlerTest.java index b2f6a001..31e6949d 100644 --- a/src/test/java/jp/co/future/uroborosql/mapping/DefaultEntityHandlerTest.java +++ b/src/test/java/jp/co/future/uroborosql/mapping/DefaultEntityHandlerTest.java @@ -8,6 +8,7 @@ import static org.junit.Assert.fail; import java.lang.reflect.Field; +import java.math.BigDecimal; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -331,6 +332,112 @@ public void testQuery4() throws Exception { } } + @Test + public void testQuery5() throws Exception { + + try (SqlAgent agent = config.agent()) { + agent.required(() -> { + TestEntity4 test1 = new TestEntity4(1L, "name1", new BigDecimal("20"), + LocalDate.of(1990, Month.APRIL, 1)); + agent.insert(test1); + TestEntity4 test2 = new TestEntity4(2L, "name2", new BigDecimal("21"), + LocalDate.of(1990, Month.MAY, 1)); + agent.insert(test2); + TestEntity4 test3 = new TestEntity4(3L, "name3", new BigDecimal("22"), + LocalDate.of(1990, Month.MAY, 1)); + agent.insert(test3); + TestEntity4 test4 = new TestEntity4(4L, "name4", new BigDecimal("23"), null); + agent.insert(test4); + + long count1 = agent.query(TestEntity4.class).count(); + assertThat(count1, is(4L)); + long count2 = agent.query(TestEntity4.class).count(TestEntity4.Names.Birthday); + assertThat(count2, is(3L)); + + BigDecimal sum = agent.query(TestEntity4.class).sum(TestEntity4.Names.Age); + assertThat(sum, is(new BigDecimal("86"))); + + BigDecimal min = agent.query(TestEntity4.class).min(TestEntity4.Names.Age); + assertThat(min, is(new BigDecimal("20"))); + + String minName = agent.query(TestEntity4.class).min(TestEntity4.Names.Name); + assertThat(minName, is("name1")); + + long max = agent.query(TestEntity4.class).max(TestEntity4.Names.Id); + assertThat(max, is(4L)); + + LocalDate maxDate = agent.query(TestEntity4.class).max(TestEntity4.Names.Birthday); + assertThat(maxDate, is(LocalDate.of(1990, Month.MAY, 1))); + }); + } + } + + @Test + public void testQuery6() throws Exception { + + try (SqlAgent agent = config.agent()) { + agent.required(() -> { + TestEntity5 test1 = new TestEntity5(1L, "name1", Optional.ofNullable(new BigDecimal("20")), + LocalDate.of(1990, Month.APRIL, 1)); + agent.insert(test1); + TestEntity5 test2 = new TestEntity5(2L, "name2", Optional.ofNullable(new BigDecimal("21")), + LocalDate.of(1990, Month.MAY, 1)); + agent.insert(test2); + TestEntity5 test3 = new TestEntity5(3L, "name3", Optional.ofNullable(new BigDecimal("22")), + LocalDate.of(1990, Month.MAY, 1)); + agent.insert(test3); + TestEntity5 test4 = new TestEntity5(4L, "name4", Optional.empty(), null); + agent.insert(test4); + + long count1 = agent.query(TestEntity5.class).count(); + assertThat(count1, is(4L)); + long count2 = agent.query(TestEntity5.class).count(TestEntity5.Names.Birthday); + assertThat(count2, is(3L)); + + Optional sum = agent.query(TestEntity5.class).sum(TestEntity5.Names.Age); + assertThat(sum.orElseThrow(IllegalStateException::new), is(new BigDecimal("63"))); + + Optional min = agent.query(TestEntity5.class).min(TestEntity5.Names.Age); + assertThat(min.orElseThrow(IllegalStateException::new), is(new BigDecimal("20"))); + + String minName = agent.query(TestEntity5.class).min(TestEntity5.Names.Name); + assertThat(minName, is("name1")); + + long max = agent.query(TestEntity5.class).max(TestEntity5.Names.Id); + assertThat(max, is(4L)); + + LocalDate maxDate = agent.query(TestEntity5.class).max(TestEntity5.Names.Birthday); + assertThat(maxDate, is(LocalDate.of(1990, Month.MAY, 1))); + + }); + } + } + + @Test + public void testQuery7() throws Exception { + + try (SqlAgent agent = config.agent()) { + agent.required(() -> { + TestEntity5 test1 = new TestEntity5(1L, "name1", Optional.empty(), + LocalDate.of(1990, Month.APRIL, 1)); + agent.insert(test1); + TestEntity5 test2 = new TestEntity5(2L, "name2", Optional.empty(), + LocalDate.of(1990, Month.MAY, 1)); + agent.insert(test2); + + Optional sum = agent.query(TestEntity5.class).sum(TestEntity5.Names.Age); + assertThat(sum.isPresent(), is(false)); + + Optional min = agent.query(TestEntity5.class).min(TestEntity5.Names.Age); + assertThat(min.isPresent(), is(false)); + + Optional max = agent.query(TestEntity5.class).max(TestEntity5.Names.Age); + assertThat(max.isPresent(), is(false)); + + }); + } + } + @Test(expected = UroborosqlRuntimeException.class) public void testQueryCountUnmatchColumn() throws Exception { try (SqlAgent agent = config.agent()) { @@ -399,9 +506,7 @@ public void testQueryWithCondition() throws Exception { TestEntity test3 = new TestEntity(3L, "name3", 20, LocalDate.of(1990, Month.JUNE, 1), Optional.empty()); agent.insert(test3); - // Equal - List list = null; - list = agent.query(TestEntity.class).equal("id", 2).collect(); + List list = agent.query(TestEntity.class).equal("id", 2).collect(); assertThat(list.size(), is(1)); assertThat(list.get(0), is(test2)); @@ -700,9 +805,8 @@ public void testQueryWithBetweenColumns() throws Exception { "name3"); agent.insert(test3); - List list = null; // Between - list = agent.query(TestHistoryEntity.class) + List list = agent.query(TestHistoryEntity.class) .betweenColumns(LocalDate.of(1990, Month.APRIL, 15), "start_at", "finish_at") .asc("id") .collect(); @@ -738,9 +842,8 @@ public void testQueryWithNotBetweenColumns() throws Exception { "name3"); agent.insert(test3); - List list = null; // Between - list = agent.query(TestHistoryEntity.class) + List list = agent.query(TestHistoryEntity.class) .notBetweenColumns(LocalDate.of(1990, Month.APRIL, 15), "start_at", "finish_at") .asc("id") .collect(); // 4/15 < start_at or 4/15 > finish_at diff --git a/src/test/java/jp/co/future/uroborosql/mapping/TestEntity4.java b/src/test/java/jp/co/future/uroborosql/mapping/TestEntity4.java new file mode 100644 index 00000000..5b7d0b66 --- /dev/null +++ b/src/test/java/jp/co/future/uroborosql/mapping/TestEntity4.java @@ -0,0 +1,124 @@ +package jp.co.future.uroborosql.mapping; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Objects; + +import jp.co.future.uroborosql.mapping.annotations.Table; +import jp.co.future.uroborosql.mapping.annotations.Version; + +@Table(name = "TEST") +public class TestEntity4 { + private Long id; + private String name; + private BigDecimal age; + private LocalDate birthday; + @Version + private Integer lockVersion = 0; + + public TestEntity4() { + } + + public TestEntity4(final Long id, final String name, final BigDecimal age, final LocalDate birthday) { + this.id = id; + this.name = name; + this.age = age; + this.birthday = birthday; + } + + public interface Names { + String Id = "id"; + String Name = "name"; + String Age = "age"; + String Birthday = "birthday"; + } + + public interface Cols { + String Id = "id"; + String Name = "name"; + String Age = "age"; + String Birthday = "birthday"; + } + + public Long getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public BigDecimal getAge() { + return this.age; + } + + public LocalDate getBirthday() { + return this.birthday; + } + + public void setId(final Long id) { + this.id = id; + } + + public void setName(final String name) { + this.name = name; + } + + public void setAge(final BigDecimal age) { + this.age = age; + } + + public void setBirthday(final LocalDate birthday) { + this.birthday = birthday; + } + + public Integer getLockVersion() { + return lockVersion; + } + + public void setLockVersion(final Integer lockVersion) { + this.lockVersion = lockVersion; + } + + @Override + public int hashCode() { + return Objects.hash(age, birthday, id, lockVersion, name); + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + TestEntity4 other = (TestEntity4) obj; + if (!Objects.equals(age, other.age)) { + return false; + } + if (!Objects.equals(birthday, other.birthday)) { + return false; + } + if (!Objects.equals(id, other.id)) { + return false; + } + if (!Objects.equals(lockVersion, other.lockVersion)) { + return false; + } + if (!Objects.equals(name, other.name)) { + return false; + } + return true; + } + + @Override + public String toString() { + return "TestEntity4 [id=" + id + ", name=" + name + ", age=" + age + ", birthday=" + birthday + ", lockVersion=" + + lockVersion + "]"; + } + +} diff --git a/src/test/java/jp/co/future/uroborosql/mapping/TestEntity5.java b/src/test/java/jp/co/future/uroborosql/mapping/TestEntity5.java new file mode 100644 index 00000000..3fae4f73 --- /dev/null +++ b/src/test/java/jp/co/future/uroborosql/mapping/TestEntity5.java @@ -0,0 +1,125 @@ +package jp.co.future.uroborosql.mapping; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Objects; +import java.util.Optional; + +import jp.co.future.uroborosql.mapping.annotations.Table; +import jp.co.future.uroborosql.mapping.annotations.Version; + +@Table(name = "TEST") +public class TestEntity5 { + private Long id; + private String name; + private Optional age; + private LocalDate birthday; + @Version + private Integer lockVersion = 0; + + public TestEntity5() { + } + + public TestEntity5(final Long id, final String name, final Optional age, final LocalDate birthday) { + this.id = id; + this.name = name; + this.age = age; + this.birthday = birthday; + } + + public interface Names { + String Id = "id"; + String Name = "name"; + String Age = "age"; + String Birthday = "birthday"; + } + + public interface Cols { + String Id = "id"; + String Name = "name"; + String Age = "age"; + String Birthday = "birthday"; + } + + public Long getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public Optional getAge() { + return this.age; + } + + public LocalDate getBirthday() { + return this.birthday; + } + + public void setId(final Long id) { + this.id = id; + } + + public void setName(final String name) { + this.name = name; + } + + public void setAge(final Optional age) { + this.age = age; + } + + public void setBirthday(final LocalDate birthday) { + this.birthday = birthday; + } + + public Integer getLockVersion() { + return lockVersion; + } + + public void setLockVersion(final Integer lockVersion) { + this.lockVersion = lockVersion; + } + + @Override + public int hashCode() { + return Objects.hash(age, birthday, id, lockVersion, name); + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + TestEntity5 other = (TestEntity5) obj; + if (!Objects.equals(age, other.age)) { + return false; + } + if (!Objects.equals(birthday, other.birthday)) { + return false; + } + if (!Objects.equals(id, other.id)) { + return false; + } + if (!Objects.equals(lockVersion, other.lockVersion)) { + return false; + } + if (!Objects.equals(name, other.name)) { + return false; + } + return true; + } + + @Override + public String toString() { + return "TestEntity5 [id=" + id + ", name=" + name + ", age=" + age + ", birthday=" + birthday + ", lockVersion=" + + lockVersion + "]"; + } + +}