title: How to create Dynamic Projections using BeanGenerator in spring data jpa?
body: <p>According to this doc, we can pass Class-based Projections into jpa api:
  <a href="https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections.dtos" rel="nofollow noreferrer">https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections.dtos</a></p>
  
  <p>so I am trying to create dynamic jpa projections using BeanGenerator, but it seems not working...
  Anyone know how to generate dynamic projection in in spring data jpa?</p>
  
  <pre><code>     final Map&lt;String, Class&lt;?&gt;&gt; properties =
                  new HashMap&lt;String, Class&lt;?&gt;&gt;();
          properties.put("name", String.class);
          properties.put("phone", String.class);
  
      final Class&lt;?&gt; beanClass = PojoGenerator.generate("com.logicbig.example.EmployeeName", properties);
         List list3 = employeeRepository.findByDept("IT", beanClass);
  
  
  
  </code></pre>
  
  <pre><code>import javassist.*;
  
  import java.io.Serializable;
  import java.util.Map;
  import java.util.Map.Entry;
  
  /**
   * copy from https://blog.javaforge.net/post/31913732423/howto-create-java-pojo-at-runtime-with-javassist
   *
   * @author blog.javaforge.net
   */
  public class PojoGenerator {
  
      public static Class generate(String className, Map&lt;String, Class&lt;?&gt;&gt; properties) throws NotFoundException,
          CannotCompileException {
  
          ClassPool pool = ClassPool.getDefault();
          CtClass declaringClass = pool.makeClass(className);
  
          // add this to define a super class to extend
          // cc.setSuperclass(resolveCtClass(MySuperClass.class));
  
          // add this to define an interface to implement
          declaringClass.addInterface(resolveCtClass(Serializable.class));
  
  
          for (Entry&lt;String, Class&lt;?&gt;&gt; entry : properties.entrySet()) {
              String fieldName = entry.getKey();
              Class&lt;?&gt; fieldClass = entry.getValue();
  
  
              declaringClass.addField(new CtField(resolveCtClass(fieldClass), fieldName, declaringClass));
  
              // add getter
              declaringClass.addMethod(generateGetter(declaringClass, fieldName, fieldClass));
  
              // add setter
              declaringClass.addMethod(generateSetter(declaringClass, fieldName, fieldClass));
  
  
          }
  
          // add constructor
          generateConstructor(declaringClass, properties);
  
          return declaringClass.toClass();
      }
  
      private static CtMethod generateGetter(CtClass declaringClass, String fieldName, Class fieldClass)
          throws CannotCompileException {
  
          String getterName = "get" + fieldName.substring(0, 1).toUpperCase()
              + fieldName.substring(1);
  
          StringBuffer sb = new StringBuffer();
          sb.append("public ").append(fieldClass.getName()).append(" ")
              .append(getterName).append("(){").append("return this.")
              .append(fieldName).append(";").append("}");
          return CtMethod.make(sb.toString(), declaringClass);
      }
  
      private static CtMethod generateSetter(CtClass declaringClass, String fieldName, Class fieldClass)
          throws CannotCompileException {
  
          String setterName = "set" + fieldName.substring(0, 1).toUpperCase()
              + fieldName.substring(1);
  
          StringBuffer sb = new StringBuffer();
          sb.append("public void ").append(setterName).append("(")
              .append(fieldClass.getName()).append(" ").append(fieldName)
              .append(")").append("{").append("this.").append(fieldName)
              .append("=").append(fieldName).append(";").append("}");
          return CtMethod.make(sb.toString(), declaringClass);
      }
  
      private static void generateConstructor(CtClass declaringClass, Map&lt;String, Class&lt;?&gt;&gt; properties)
          throws CannotCompileException {
  
  
          String constructorMethodName = declaringClass.getSimpleName();
          StringBuffer constructorMethod = new StringBuffer();
          StringBuffer constructorBody = new StringBuffer();
  
          constructorMethod.append("public ").append(constructorMethodName).append("(");
          for (Entry&lt;String, Class&lt;?&gt;&gt; entry : properties.entrySet()) {
              String fieldName = entry.getKey();
              Class&lt;?&gt; fieldClass = entry.getValue();
  
              // add constructor
              constructorMethod.append(fieldClass.getName()).append(" ").append(fieldName).append(",");
              constructorBody.append("this.").append(fieldName)
                  .append("=").append(fieldName).append(";");
          }
          constructorMethod.deleteCharAt(constructorMethod.lastIndexOf(","));
          constructorMethod.append(") {");
          constructorMethod.append(constructorBody);
          constructorMethod.append("}");
  
          System.out.println(constructorMethod);
          CtConstructor constructor = CtNewConstructor.make(constructorMethod.toString(), declaringClass);
          declaringClass.addConstructor(constructor);
  
          CtConstructor defaultConstructor = CtNewConstructor.make("public " + constructorMethodName + "() {}", declaringClass);
          declaringClass.addConstructor(defaultConstructor);
      }
  
      private static CtClass resolveCtClass(Class clazz) throws NotFoundException {
          ClassPool pool = ClassPool.getDefault();
          return pool.get(clazz.getName());
      }
  }
  </code></pre>
  
  <pre><code>====== finding beanClass for IT dept =====
  13:50:12.495 [main] DEBUG org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler - Creating new EntityManager for shared EntityManager invocation
  13:50:12.495 [main] DEBUG org.hibernate.query.criteria.internal.CriteriaQueryImpl - Rendered criteria query -&gt; select generatedAlias0 from Employee as generatedAlias0 where generatedAlias0.dept=:param0
  13:50:12.496 [main] DEBUG org.hibernate.hql.internal.ast.QueryTranslatorImpl - parse() - HQL: select generatedAlias0 from com.logicbig.example.Employee as generatedAlias0 where generatedAlias0.dept=:param0
  13:50:12.497 [main] DEBUG org.hibernate.hql.internal.ast.ErrorTracker - throwQueryException() : no errors
  13:50:12.498 [main] DEBUG org.hibernate.hql.internal.ast.QueryTranslatorImpl - --- HQL AST ---
   \-[QUERY] Node: 'query'
      +-[SELECT_FROM] Node: 'SELECT_FROM'
      |  +-[FROM] Node: 'from'
      |  |  \-[RANGE] Node: 'RANGE'
      |  |     +-[DOT] Node: '.'
      |  |     |  +-[DOT] Node: '.'
      |  |     |  |  +-[DOT] Node: '.'
      |  |     |  |  |  +-[IDENT] Node: 'com'
      |  |     |  |  |  \-[IDENT] Node: 'logicbig'
      |  |     |  |  \-[IDENT] Node: 'example'
      |  |     |  \-[IDENT] Node: 'Employee'
      |  |     \-[ALIAS] Node: 'generatedAlias0'
      |  \-[SELECT] Node: 'select'
      |     \-[IDENT] Node: 'generatedAlias0'
      \-[WHERE] Node: 'where'
         \-[EQ] Node: '='
            +-[DOT] Node: '.'
            |  +-[IDENT] Node: 'generatedAlias0'
            |  \-[IDENT] Node: 'dept'
            \-[COLON] Node: ':'
               \-[IDENT] Node: 'param0'
  
  13:50:12.498 [main] DEBUG org.hibernate.hql.internal.antlr.HqlSqlBaseWalker - select &lt;&lt; begin [level=1, statement=select]
  13:50:12.499 [main] DEBUG org.hibernate.hql.internal.ast.tree.FromElement - FromClause{level=1} : com.logicbig.example.Employee (generatedAlias0) -&gt; employee0_
  13:50:12.499 [main] DEBUG org.hibernate.hql.internal.ast.tree.FromReferenceNode - Resolved : generatedAlias0 -&gt; employee0_.id
  13:50:12.500 [main] DEBUG org.hibernate.hql.internal.ast.tree.FromReferenceNode - Resolved : generatedAlias0 -&gt; employee0_.id
  13:50:12.500 [main] DEBUG org.hibernate.hql.internal.ast.tree.DotNode - getDataType() : dept -&gt; org.hibernate.type.StringType@6b63d445
  13:50:12.500 [main] DEBUG org.hibernate.hql.internal.ast.tree.FromReferenceNode - Resolved : generatedAlias0.dept -&gt; employee0_.dept
  13:50:12.500 [main] DEBUG org.hibernate.hql.internal.antlr.HqlSqlBaseWalker - select : finishing up [level=1, statement=select]
  13:50:12.500 [main] DEBUG org.hibernate.hql.internal.ast.HqlSqlWalker - processQuery() :  ( SELECT ( {select clause} employee0_.id ) ( FromClause{level=1} Employee employee0_ ) ( where ( = ( employee0_.dept employee0_.id dept ) ? ) ) )
  13:50:12.509 [main] DEBUG org.hibernate.hql.internal.ast.util.JoinProcessor - Using FROM fragment [Employee employee0_]
  13:50:12.509 [main] DEBUG org.hibernate.hql.internal.antlr.HqlSqlBaseWalker - select &gt;&gt; end [level=1, statement=select]
  13:50:12.510 [main] DEBUG org.hibernate.hql.internal.ast.QueryTranslatorImpl - --- SQL AST ---
   \-[SELECT] QueryNode: 'SELECT'  querySpaces (Employee)
      +-[SELECT_CLAUSE] SelectClause: '{select clause}'
      |  +-[ALIAS_REF] IdentNode: 'employee0_.id as id1_0_' {alias=generatedAlias0, className=com.logicbig.example.Employee, tableAlias=employee0_}
      |  \-[SQL_TOKEN] SqlFragment: 'employee0_.dept as dept2_0_, employee0_.name as name3_0_, employee0_.phone as phone4_0_, employee0_.salary as salary5_0_'
      +-[FROM] FromClause: 'from' FromClause{level=1, fromElementCounter=1, fromElements=1, fromElementByClassAlias=[generatedAlias0], fromElementByTableAlias=[employee0_], fromElementsByPath=[], collectionJoinFromElementsByPath=[], impliedElements=[]}
      |  \-[FROM_FRAGMENT] FromElement: 'Employee employee0_' FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=generatedAlias0,role=null,tableName=Employee,tableAlias=employee0_,origin=null,columns={,className=com.logicbig.example.Employee}}
      \-[WHERE] SqlNode: 'where'
         \-[EQ] BinaryLogicOperatorNode: '='
            +-[DOT] DotNode: 'employee0_.dept' {propertyName=dept,dereferenceType=PRIMITIVE,getPropertyPath=dept,path=generatedAlias0.dept,tableAlias=employee0_,className=com.logicbig.example.Employee,classAlias=generatedAlias0}
            |  +-[ALIAS_REF] IdentNode: 'employee0_.id' {alias=generatedAlias0, className=com.logicbig.example.Employee, tableAlias=employee0_}
            |  \-[IDENT] IdentNode: 'dept' {originalText=dept}
            \-[NAMED_PARAM] ParameterNode: '?' {name=param0, expectedType=org.hibernate.type.StringType@6b63d445}
  
  13:50:12.510 [main] DEBUG org.hibernate.hql.internal.ast.ErrorTracker - throwQueryException() : no errors
  13:50:12.510 [main] DEBUG org.hibernate.hql.internal.ast.QueryTranslatorImpl - HQL: select generatedAlias0 from com.logicbig.example.Employee as generatedAlias0 where generatedAlias0.dept=:param0
  13:50:12.510 [main] DEBUG org.hibernate.hql.internal.ast.QueryTranslatorImpl - SQL: select employee0_.id as id1_0_, employee0_.dept as dept2_0_, employee0_.name as name3_0_, employee0_.phone as phone4_0_, employee0_.salary as salary5_0_ from Employee employee0_ where employee0_.dept=?
  13:50:12.510 [main] DEBUG org.hibernate.hql.internal.ast.ErrorTracker - throwQueryException() : no errors
  13:50:12.511 [main] DEBUG org.hibernate.SQL - select employee0_.id as id1_0_, employee0_.dept as dept2_0_, employee0_.name as name3_0_, employee0_.phone as phone4_0_, employee0_.salary as salary5_0_ from Employee employee0_ where employee0_.dept=?
  13:50:12.512 [main] DEBUG org.hibernate.loader.Loader - Result set row: 0
  13:50:12.515 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[com.logicbig.example.Employee#2]
  13:50:12.520 [main] DEBUG org.hibernate.loader.Loader - Result set row: 1
  13:50:12.521 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[com.logicbig.example.Employee#5]
  13:50:12.521 [main] DEBUG org.hibernate.loader.Loader - Result set row: 2
  13:50:12.521 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[com.logicbig.example.Employee#6]
  13:50:12.521 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Resolving associations for [com.logicbig.example.Employee#2]
  13:50:12.522 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done materializing entity [com.logicbig.example.Employee#2]
  13:50:12.522 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Resolving associations for [com.logicbig.example.Employee#5]
  13:50:12.522 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done materializing entity [com.logicbig.example.Employee#5]
  13:50:12.522 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Resolving associations for [com.logicbig.example.Employee#6]
  13:50:12.522 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done materializing entity [com.logicbig.example.Employee#6]
  13:50:12.522 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
  13:50:12.523 [main] DEBUG org.springframework.orm.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
  Exception in thread "main" org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [com.logicbig.example.Employee] to type [com.logicbig.example.EmployeeName]
      at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321)
      at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194)
      at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174)
      at org.springframework.data.repository.query.ResultProcessor$ProjectingConverter.convert(ResultProcessor.java:293)
      at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.lambda$and$0(ResultProcessor.java:213)
      at org.springframework.data.repository.query.ResultProcessor$ChainingConverter.convert(ResultProcessor.java:224)
      at org.springframework.data.repository.query.ResultProcessor.processResult(ResultProcessor.java:152)
      at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:141)
      at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:125)
      at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:590)
      at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:578)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
      at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
      at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
      at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
      at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
      at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
      at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
      at com.sun.proxy.$Proxy34.findByDept(Unknown Source)
      at com.logicbig.example.ExampleClient.run(ExampleClient.java:74)
      at com.logicbig.example.ExampleMain.main(ExampleMain.java:12)
  13:50:26.941 [pool-1-thread-1] DEBUG org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl - Connection pool now considered primed; min-size will be maintained
  
  
  </code></pre>