diff --git a/common/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapper.java b/common/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapper.java
index 83074b5..e89de3e 100644
--- a/common/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapper.java
+++ b/common/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapper.java
@@ -48,6 +48,13 @@ public interface JdbcMapper extends Closeable {
DatabaseType databaseType() default DatabaseType.DEFAULT;
String arrayNumberTypeName() default "";
String arrayStringTypeName() default "";
+
+ /**
+ * Allows consumer of JdbcMapper.Mapper to generate DaoBean with Spring Boot Stereotype @Repository
+ * Defaults to false
+ * @return
+ */
+ OptionalBool generateAsSpringBean() default OptionalBool.FALSE;
}
@Retention(RetentionPolicy.SOURCE)
diff --git a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java
index 34f58c2..25c86be 100644
--- a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java
+++ b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java
@@ -10,6 +10,7 @@ import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
import java.io.*;
+import java.net.URL;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
@@ -30,7 +31,7 @@ import static com.moparisthebest.jdbc.codegen.JdbcMapperFactory.SUFFIX;
* Created by mopar on 5/24/17.
*/
@SupportedAnnotationTypes("com.moparisthebest.jdbc.codegen.JdbcMapper.Mapper")
-@SupportedOptions({"jdbcMapper.databaseType", "jdbcMapper.arrayNumberTypeName", "jdbcMapper.arrayStringTypeName", "jdbcMapper.allowedMaxRowParamNames", "jdbcMapper.sqlCheckerClass"})
+@SupportedOptions({"jdbcMapper.databaseType", "jdbcMapper.arrayNumberTypeName", "jdbcMapper.arrayStringTypeName", "jdbcMapper.allowedMaxRowParamNames", "jdbcMapper.sqlCheckerClass", "jdbcMapper.generateAsSpringBean"})
public class JdbcMapperProcessor extends AbstractProcessor {
public static final Pattern paramPattern = Pattern.compile("\\{(([^\\s]+)\\s+(([Nn][Oo][Tt]\\s+)?[Ii][Nn]\\s+))?([BbCc][Ll][Oo][Bb]\\s*:\\s*([^:}]+\\s*:\\s*)?)?([^}]+)\\}");
@@ -171,6 +172,8 @@ public class JdbcMapperProcessor extends AbstractProcessor {
final JdbcMapper.Mapper mapper = genClass.getAnnotation(JdbcMapper.Mapper.class);
final JdbcMapper.DatabaseType databaseType;
final String arrayNumberTypeName, arrayStringTypeName;
+ final boolean generateAsSpringBean = mapper.generateAsSpringBean().combine(false);
+
if (mapper.databaseType() == JdbcMapper.DatabaseType.DEFAULT) {
databaseType = defaultDatabaseType;
arrayNumberTypeName = !mapper.arrayNumberTypeName().isEmpty() ? mapper.arrayNumberTypeName() : defaultArrayNumberTypeName;
@@ -223,10 +226,16 @@ public class JdbcMapperProcessor extends AbstractProcessor {
w.write(packageName);
w.write(";\n\n");
}
+ if (generateAsSpringBean) {
+ w.write("import org.springframework.stereotype.Repository;\n\n");
+ }
w.write("import com.moparisthebest.jdbc.Factory;\n\n");
w.write("import java.sql.*;\n\n");
w.write("import static com.moparisthebest.jdbc.util.ResultSetUtil.*;\n");
w.write("import static com.moparisthebest.jdbc.TryClose.tryClose;\n\n");
+ if (generateAsSpringBean) {
+ w.write("@Repository\n");
+ }
w.write("public class ");
w.write(className);
if (isInterface) {
@@ -1105,4 +1114,13 @@ public class JdbcMapperProcessor extends AbstractProcessor {
}
return false;
}
+
+ private final boolean isSpringRepositoryStereotypeRequired(final String stereoType) {
+
+ if (Boolean.parseBoolean(processingEnv.getOptions().get("jdbcMapper.generateAsSpringBean"))) {
+ return processingEnv.getOptions().get("jdbcMapper.springBeanStereotype").equalsIgnoreCase(stereoType);
+ }
+
+ return false;
+ }
}
diff --git a/readme.md b/readme.md
index a605990..7f704d7 100644
--- a/readme.md
+++ b/readme.md
@@ -411,6 +411,49 @@ String s = rs.getString(index);
return s == null ? null : ZoneOffset.of(s);
```
+Spring Boot Support
+----
+Configuring your `JdbcMapperProcessor` generated `DAOBean` to be compatible with Spring's [ComponentScan](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/ComponentScan.html) can be
+accomplished by simply setting the `JdbcMapper.Mapper.generateAsSpringBean` value to
+`JdbcMapper.OptionalBool.TRUE`. This value is set to `JdbcMapper.OptionalBool.FALSE` by default.
+```java
+@JdbcMapper.Mapper(generateAsSpringBean = JdbcMapper.OptionalBool.TRUE)
+public interface MyDAO extends JdbcMapper {
+ // Your method signatures and queries here
+}
+```
+
+This configuration will generate a DAOBean looking something like this:
+```java
+package com.yourpackage;
+
+import org.springframework.stereotype.Repository;
+
+import com.moparisthebest.jdbc.Factory;
+
+import java.sql.*;
+
+import static com.moparisthebest.jdbc.util.ResultSetUtil.*;
+import static com.moparisthebest.jdbc.TryClose.tryClose;
+
+@Repository
+public class MyDAOBean implements MyDAO {
+ // Generated code here
+}
+```
+
+Your DAOBean can now be [Autowired](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/annotation/Autowired.html)
+in a Spring Boot application:
+```java
+private final MyDAO myDAO;
+
+@Autowired
+public MyController(MyDAO myDAO) {
+ this.myDAO = myDAO;
+}
+
+```
+
TODO
----
diff --git a/test/pom.xml b/test/pom.xml
index a81d3f7..af98f8d 100644
--- a/test/pom.xml
+++ b/test/pom.xml
@@ -80,6 +80,11 @@
test
true
+
+ org.springframework
+ spring-context
+ 5.0.9.RELEASE
+
diff --git a/test/src/main/java/com/moparisthebest/jdbc/codegen/AbstractSpringBeanDAO.java b/test/src/main/java/com/moparisthebest/jdbc/codegen/AbstractSpringBeanDAO.java
new file mode 100644
index 0000000..552f85a
--- /dev/null
+++ b/test/src/main/java/com/moparisthebest/jdbc/codegen/AbstractSpringBeanDAO.java
@@ -0,0 +1,9 @@
+package com.moparisthebest.jdbc.codegen;
+
+@JdbcMapper.Mapper(jndiName = "bob",
+ databaseType = JdbcMapper.DatabaseType.ANY,
+ cachePreparedStatements = JdbcMapper.OptionalBool.FALSE,
+ allowReflection = JdbcMapper.OptionalBool.TRUE,
+ generateAsSpringBean = JdbcMapper.OptionalBool.TRUE)
+public abstract class AbstractSpringBeanDAO implements JdbcMapper {
+}
diff --git a/test/src/main/java/com/moparisthebest/jdbc/codegen/SpringBeanDAO.java b/test/src/main/java/com/moparisthebest/jdbc/codegen/SpringBeanDAO.java
new file mode 100644
index 0000000..62e7b1e
--- /dev/null
+++ b/test/src/main/java/com/moparisthebest/jdbc/codegen/SpringBeanDAO.java
@@ -0,0 +1,9 @@
+package com.moparisthebest.jdbc.codegen;
+
+@JdbcMapper.Mapper(jndiName = "bob",
+ databaseType = JdbcMapper.DatabaseType.ANY,
+ cachePreparedStatements = JdbcMapper.OptionalBool.FALSE,
+ allowReflection = JdbcMapper.OptionalBool.TRUE,
+ generateAsSpringBean = JdbcMapper.OptionalBool.TRUE)
+public interface SpringBeanDAO extends JdbcMapper {
+}
diff --git a/test/src/test/java/com/moparisthebest/jdbc/codegen/SpringBeanDAOTest.java b/test/src/test/java/com/moparisthebest/jdbc/codegen/SpringBeanDAOTest.java
new file mode 100644
index 0000000..cbc3a70
--- /dev/null
+++ b/test/src/test/java/com/moparisthebest/jdbc/codegen/SpringBeanDAOTest.java
@@ -0,0 +1,59 @@
+package com.moparisthebest.jdbc.codegen;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+public class SpringBeanDAOTest {
+
+ @Test
+ public void testSpringBeanDAOBeanImportsRepository() {
+ try {
+ String genClass = new String(Files.readAllBytes(Paths.get("target/generated-sources/annotations/com/moparisthebest/jdbc/codegen/SpringBeanDAOBean.java")), StandardCharsets.UTF_8);
+ assertTrue(genClass.contains("import org.springframework.stereotype.Repository;"));
+ } catch (IOException e) {
+ assertFalse("Failed to read file at target/generated-sources/annotations/com/moparisthebest/jdbc/codegen/SpringBeanDAOBean.java", true);
+ }
+ }
+
+ @Test
+ public void testSpringBeanDAOHasRepositoryStereotype() {
+ try {
+ Class clazz = ClassLoader.getSystemClassLoader()
+ .loadClass("com.moparisthebest.jdbc.codegen.SpringBeanDAOBean");
+ assertTrue(clazz.isAnnotationPresent(org.springframework.stereotype.Repository.class));
+ } catch (ClassNotFoundException e) {
+ assertFalse("Failed to find class com.moparisthebest.jdbc.codegen.SpringBeanDAOBean", true);
+ }
+ }
+
+ @Test
+ public void testSpringBeanDAOBeanImplementsSpringBeanDAO() {
+ try {
+ Class[] clazzInterfaces = ClassLoader.getSystemClassLoader()
+ .loadClass("com.moparisthebest.jdbc.codegen.SpringBeanDAOBean").getInterfaces();
+ assertTrue(Arrays.asList(clazzInterfaces).contains(SpringBeanDAO.class));
+ } catch (ClassNotFoundException e) {
+ assertFalse("Failed to find class com.moparisthebest.jdbc.codegen.SpringBeanDAOBean", true);
+ }
+ }
+
+
+ @Test
+ public void testAbstractSpringBeanDAOBeanExtendsAbstractSpringBeanDAO() {
+ try {
+ Class clazz = ClassLoader.getSystemClassLoader()
+ .loadClass("com.moparisthebest.jdbc.codegen.AbstractSpringBeanDAOBean");
+ assertTrue(clazz.getSuperclass().equals(AbstractSpringBeanDAO.class));
+ } catch (ClassNotFoundException e) {
+ assertFalse("Failed to find class com.moparisthebest.jdbc.codegen.AbstractSpringBeanDAOBean", true);
+ }
+ }
+}