Search code examples
spring-data-jdbc

Spring Data JDBC - Lazy Loading/Projection


For Spring Data JDBC, is lazy loading possible ? Or is projection possible ?

I would only want two fields in my data but it seems that Spring JDBC is fetching the whole thing.

@Repository
public interface AppUserRepo extends CrudRepository<AppUser, Long> {
    @Query("select id, firstname, lastname from m_appuser where firstname=:firstName")
    public AppUser findByAppUserName(@Param("firstName") String firstName);
}

This resulted to getting all associated objects.


org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT "ROLE"."ID" AS "ID", "ROLE"."DEL" AS "DEL", "ROLE"."NAME" AS "NAME", "ROLE"."VERSION" AS "VERSION", "ROLE"."DISABLED" AS "DISABLED", "ROLE"."CREATED_DATE" AS "CREATED_DATE", "ROLE"."DESCRIPTION" AS "DESCRIPTION", "ROLE"."REFERENCE_NUMBER" AS "REFERENCE_NUMBER", "ROLE"."LAST_MODIFIED_DATE" AS "LAST_MODIFIED_DATE", "createdBy"."ID" AS "CREATEDBY_ID", "createdBy"."DEL" AS "CREATEDBY_DEL", "createdBy"."EMAIL" AS "CREATEDBY_EMAIL", "createdBy"."STATUS" AS "CREATEDBY_STATUS", "createdBy"."VERSION" AS "CREATEDBY_VERSION", "createdBy"."ENABLED" AS "CREATEDBY_ENABLED", "createdBy"."PASSWORD" AS "CREATEDBY_PASSWORD", "createdBy"."USER_TYPE" AS "CREATEDBY_USER_TYPE", "createdBy"."BRANCH_ID" AS "CREATEDBY_BRANCH_ID", "createdBy"."USERNAME" AS "CREATEDBY_USERNAME", "createdBy"."LASTNAME" AS "CREATEDBY_LASTNAME", "createdBy"."FIRSTNAME" AS "CREATEDBY_FIRSTNAME", "createdBy"."CLEAR_PSWD" AS "CREATEDBY_CLEAR_PSWD", "createdBy"."MIDDLENAME" AS "CREATEDBY_MIDDLENAME", "createdBy"."CREATED_DATE" AS "CREATEDBY_CREATED_DATE", "createdBy"."FAILED_LOGINS" AS "CREATEDBY_FAILED_LOGINS", "createdBy"."MOBILE_NUMBER" AS "CREATEDBY_MOBILE_NUMBER", "createdBy"."LAST_LOGIN_DATE" AS "CREATEDBY_LAST_LOGIN_DATE", "createdBy"."LAST_MODIFIED_DATE" AS "CREATEDBY_LAST_MODIFIED_DATE", "createdBy"."ACCOUNT_NON_LOCKED" AS "CREATEDBY_ACCOUNT_NON_LOCKED", "createdBy"."PROFILE_EXPIRY_DATE" AS "CREATEDBY_PROFILE_EXPIRY_DATE", "createdBy"."IS_SELF_SERVICE_USER" AS "CREATEDBY_IS_SELF_SERVICE_USER", "createdBy"."MOBILE_COUNTRY_CODE" AS "CREATEDBY_MOBILE_COUNTRY_CODE", "createdBy"."ACCOUNT_NON_EXPIRED" AS "CREATEDBY_ACCOUNT_NON_EXPIRED", "createdBy"."PASSWORD_NEVER_EXPIRES" AS "CREATEDBY_PASSWORD_NEVER_EXPIRES", "createdBy"."CREDENTIALS_NON_EXPIRED" AS "CREATEDBY_CREDENTIALS_NON_EXPIRED", "createdBy"."LAST_TIME_PASSWORD_UPDATED" AS "CREATEDBY_LAST_TIME_PASSWORD_UPDATED", "createdBy"."FIRST_TIME_LOGIN_REMAINING" AS "CREATEDBY_FIRST_TIME_LOGIN_REMAINING", "lastModifiedBy"."ID" AS "LASTMODIFIEDBY_ID", "lastModifiedBy"."DEL" AS "LASTMODIFIEDBY_DEL", "lastModifiedBy"."EMAIL" AS "LASTMODIFIEDBY_EMAIL", "lastModifiedBy"."STATUS" AS "LASTMODIFIEDBY_STATUS", "lastModifiedBy"."VERSION" AS "LASTMODIFIEDBY_VERSION", "lastModifiedBy"."ENABLED" AS "LASTMODIFIEDBY_ENABLED", "lastModifiedBy"."USERNAME" AS "LASTMODIFIEDBY_USERNAME", "lastModifiedBy"."BRANCH_ID" AS "LASTMODIFIEDBY_BRANCH_ID", "lastModifiedBy"."PASSWORD" AS "LASTMODIFIEDBY_PASSWORD", "lastModifiedBy"."LASTNAME" AS "LASTMODIFIEDBY_LASTNAME", "lastModifiedBy"."USER_TYPE" AS "LASTMODIFIEDBY_USER_TYPE", "lastModifiedBy"."CLEAR_PSWD" AS "LASTMODIFIEDBY_CLEAR_PSWD", "lastModifiedBy"."FIRSTNAME" AS "LASTMODIFIEDBY_FIRSTNAME", "lastModifiedBy"."MIDDLENAME" AS "LASTMODIFIEDBY_MIDDLENAME", "lastModifiedBy"."CREATED_DATE" AS "LASTMODIFIEDBY_CREATED_DATE", "lastModifiedBy"."FAILED_LOGINS" AS "LASTMODIFIEDBY_FAILED_LOGINS", "lastModifiedBy"."MOBILE_NUMBER" AS "LASTMODIFIEDBY_MOBILE_NUMBER", "lastModifiedBy"."LAST_LOGIN_DATE" AS "LASTMODIFIEDBY_LAST_LOGIN_DATE", "lastModifiedBy"."ACCOUNT_NON_LOCKED" AS "LASTMODIFIEDBY_ACCOUNT_NON_LOCKED", "lastModifiedBy"."LAST_MODIFIED_DATE" AS "LASTMODIFIEDBY_LAST_MODIFIED_DATE", "lastModifiedBy"."MOBILE_COUNTRY_CODE" AS "LASTMODIFIEDBY_MOBILE_COUNTRY_CODE", "lastModifiedBy"."PROFILE_EXPIRY_DATE" AS "LASTMODIFIEDBY_PROFILE_EXPIRY_DATE", "lastModifiedBy"."ACCOUNT_NON_EXPIRED" AS "LASTMODIFIEDBY_ACCOUNT_NON_EXPIRED", "lastModifiedBy"."IS_SELF_SERVICE_USER" AS "LASTMODIFIEDBY_IS_SELF_SERVICE_USER", "lastModifiedBy"."PASSWORD_NEVER_EXPIRES" AS "LASTMODIFIEDBY_PASSWORD_NEVER_EXPIRES", "lastModifiedBy"."CREDENTIALS_NON_EXPIRED" AS "LASTMODIFIEDBY_CREDENTIALS_NON_EXPIRED", "lastModifiedBy"."FIRST_TIME_LOGIN_REMAINING" AS "LASTMODIFIEDBY_FIRST_TIME_LOGIN_REMAINING", "lastModifiedBy"."LAST_TIME_PASSWORD_UPDATED" AS "LASTMODIFIEDBY_LAST_TIME_PASSWORD_UPDATED", "createdBy_staff"."ID" AS "CREATEDBY_STAFF_ID", "createdBy_staff"."ACTIVE" AS "CREATEDBY_STAFF_ACTIVE", "createdBy_staff"."MOBILE_NO" AS "CREATEDBY_STAFF_MOBILE_NO", "createdBy_staff"."LASTNAME" AS "CREATEDBY_STAFF_LASTNAME", "createdBy_staff"."FIRSTNAME" AS "CREATEDBY_STAFF_FIRSTNAME", "createdBy_staff"."EXTERNAL_ID" AS "CREATEDBY_STAFF_EXTERNAL_ID", "createdBy_staff"."LOAN_OFFICER" AS "CREATEDBY_STAFF_LOAN_OFFICER", "createdBy_staff"."DISPLAY_NAME" AS "CREATEDBY_STAFF_DISPLAY_NAME", "createdBy_staff"."JOINING_DATE" AS "CREATEDBY_STAFF_JOINING_DATE", "createdBy_staff"."EMAIL_ADDRESS" AS "CREATEDBY_STAFF_EMAIL_ADDRESS", "createdBy_staff"."ORGANISATIONAL_ROLE_TYPE" AS "CREATEDBY_STAFF_ORGANISATIONAL_ROLE_TYPE", "createdBy_office"."ID" AS "CREATEDBY_OFFICE_ID", "createdBy_office"."NAME" AS "CREATEDBY_OFFICE_NAME", "createdBy_office"."HIERARCHY" AS "CREATEDBY_OFFICE_HIERARCHY", "createdBy_office"."EXTERNAL_ID" AS "CREATEDBY_OFFICE_EXTERNAL_ID", "createdBy_office"."OPENING_DATE" AS "CREATEDBY_OFFICE_OPENING_DATE", "createdBy_tellerId"."ID" AS "CREATEDBY_TELLERID_ID", "createdBy_tellerId"."DEL" AS "CREATEDBY_TELLERID_DEL", "createdBy_tellerId"."NAME" AS "CREATEDBY_TELLERID_NAME", "createdBy_tellerId"."VERSION" AS "CREATEDBY_TELLERID_VERSION", "createdBy_tellerId"."TELLER_CODE" AS "CREATEDBY_TELLERID_TELLER_CODE", "createdBy_tellerId"."DESCRIPTION" AS "CREATEDBY_TELLERID_DESCRIPTION", "createdBy_tellerId"."CREATED_DATE" AS "CREATEDBY_TELLERID_CREATED_DATE", "createdBy_tellerId"."LAST_MODIFIED_DATE" AS "CREATEDBY_TELLERID_LAST_MODIFIED_DATE", "createdBy_departmentId"."ID" AS "CREATEDBY_DEPARTMENTID_ID", "createdBy_departmentId"."DEL" AS "CREATEDBY_DEPARTMENTID_DEL", "createdBy_departmentId"."VERSION" AS "CREATEDBY_DEPARTMENTID_VERSION", "createdBy_departmentId"."CREATED_DATE" AS "CREATEDBY_DEPARTMENTID_CREATED_DATE", "createdBy_departmentId"."DEPARTMENT_NAME" AS "CREATEDBY_DEPARTMENTID_DEPARTMENT_NAME", "createdBy_departmentId"."DEPARTMENT_CODE" AS "CREATEDBY_DEPARTMENTID_DEPARTMENT_CODE", "createdBy_departmentId"."REFERENCE_NUMBER" AS "CREATEDBY_DEPARTMENTID_REFERENCE_NUMBER", "createdBy_departmentId"."LAST_MODIFIED_DATE" AS "CREATEDBY_DEPARTMENTID_LAST_MODIFIED_DATE", "lastModifiedBy_staff"."ID" AS "LASTMODIFIEDBY_STAFF_ID", "lastModifiedBy_staff"."ACTIVE" AS "LASTMODIFIEDBY_STAFF_ACTIVE", "lastModifiedBy_staff"."MOBILE_NO" AS "LASTMODIFIEDBY_STAFF_MOBILE_NO", "lastModifiedBy_staff"."LASTNAME" AS "LASTMODIFIEDBY_STAFF_LASTNAME", "lastModifiedBy_staff"."FIRSTNAME" AS "LASTMODIFIEDBY_STAFF_FIRSTNAME", "lastModifiedBy_staff"."EXTERNAL_ID" AS "LASTMODIFIEDBY_STAFF_EXTERNAL_ID", "lastModifiedBy_staff"."DISPLAY_NAME" AS "LASTMODIFIEDBY_STAFF_DISPLAY_NAME", "lastModifiedBy_staff"."LOAN_OFFICER" AS "LASTMODIFIEDBY_STAFF_LOAN_OFFICER", "lastModifiedBy_staff"."JOINING_DATE" AS "LASTMODIFIEDBY_STAFF_JOINING_DATE", "lastModifiedBy_staff"."EMAIL_ADDRESS" AS "LASTMODIFIEDBY_STAFF_EMAIL_ADDRESS", "lastModifiedBy_staff"."ORGANISATIONAL_ROLE_TYPE" AS "LASTMODIFIEDBY_STAFF_ORGANISATIONAL_ROLE_TYPE", "lastModifiedBy_office"."ID" AS "LASTMODIFIEDBY_OFFICE_ID", "lastModifiedBy_office"."NAME" AS "LASTMODIFIEDBY_OFFICE_NAME", "lastModifiedBy_office"."HIERARCHY" AS "LASTMODIFIEDBY_OFFICE_HIERARCHY", "lastModifiedBy_office"."EXTERNAL_ID" AS "LASTMODIFIEDBY_OFFICE_EXTERNAL_ID", "lastModifiedBy_office"."OPENING_DATE" AS "LASTMODIFIEDBY_OFFICE_OPENING_DATE", "lastModifiedBy_tellerId"."ID" AS "LASTMODIFIEDBY_TELLERID_ID", "lastModifiedBy_tellerId"."DEL" AS "LASTMODIFIEDBY_TELLERID_DEL", "lastModifiedBy_tellerId"."NAME" AS "LASTMODIFIEDBY_TELLERID_NAME", "lastModifiedBy_tellerId"."VERSION" AS "LASTMODIFIEDBY_TELLERID_VERSION", "lastModifiedBy_tellerId"."TELLER_CODE" AS "LASTMODIFIEDBY_TELLERID_TELLER_CODE", "lastModifiedBy_tellerId"."CREATED_DATE" AS "LASTMODIFIEDBY_TELLERID_CREATED_DATE", "lastModifiedBy_tellerId"."DESCRIPTION" AS "LASTMODIFIEDBY_TELLERID_DESCRIPTION", "lastModifiedBy_tellerId"."LAST_MODIFIED_DATE" AS "LASTMODIFIEDBY_TELLERID_LAST_MODIFIED_DATE", "lastModifiedBy_departmentId"."ID" AS "LASTMODIFIEDBY_DEPARTMENTID_ID", "lastModifiedBy_departmentId"."DEL" AS "LASTMODIFIEDBY_DEPARTMENTID_DEL", "lastModifiedBy_departmentId"."VERSION" AS "LASTMODIFIEDBY_DEPARTMENTID_VERSION", "lastModifiedBy_departmentId"."CREATED_DATE" AS "LASTMODIFIEDBY_DEPARTMENTID_CREATED_DATE", "lastModifiedBy_departmentId"."DEPARTMENT_CODE" AS "LASTMODIFIEDBY_DEPARTMENTID_DEPARTMENT_CODE", "lastModifiedBy_departmentId"."DEPARTMENT_NAME" AS "LASTMODIFIEDBY_DEPARTMENTID_DEPARTMENT_NAME", "lastModifiedBy_departmentId"."REFERENCE_NUMBER" AS "LASTMODIFIEDBY_DEPARTMENTID_REFERENCE_NUMBER", "lastModifiedBy_departmentId"."LAST_MODIFIED_DATE" AS "LASTMODIFIEDBY_DEPARTMENTID_LAST_MODIFIED_DATE", "createdBy_staff_image"."ID" AS "CREATEDBY_STAFF_IMAGE_ID", "createdBy_staff_image"."LOCATION" AS "CREATEDBY_STAFF_IMAGE_LOCATION", "createdBy_staff_image"."STORAGE_TYPE" AS "CREATEDBY_STAFF_IMAGE_STORAGE_TYPE", "createdBy_staff_office"."ID" AS "CREATEDBY_STAFF_OFFICE_ID", "createdBy_staff_office"."NAME" AS "CREATEDBY_STAFF_OFFICE_NAME", "createdBy_staff_office"."HIERARCHY" AS "CREATEDBY_STAFF_OFFICE_HIERARCHY", "createdBy_staff_office"."EXTERNAL_ID" AS "CREATEDBY_STAFF_OFFICE_EXTERNAL_ID", "createdBy_staff_office"."OPENING_DATE" AS "CREATEDBY_STAFF_OFFICE_OPENING_DATE", "createdBy_departmentId_branch"."ID" AS "CREATEDBY_DEPARTMENTID_BRANCH_ID", "createdBy_departmentId_branch"."NAME" AS "CREATEDBY_DEPARTMENTID_BRANCH_NAME", "createdBy_departmentId_branch"."HIERARCHY" AS "CREATEDBY_DEPARTMENTID_BRANCH_HIERARCHY", "createdBy_departmentId_branch"."EXTERNAL_ID" AS "CREATEDBY_DEPARTMENTID_BRANCH_EXTERNAL_ID", "createdBy_departmentId_branch"."OPENING_DATE" AS "CREATEDBY_DEPARTMENTID_BRANCH_OPENING_DATE", "createdBy_departmentId_sourcePlaceCode"."ID" AS "CREATEDBY_DEPARTMENTID_SOURCEPLACECODE_ID", "createdBy_departmentId_sourcePlaceCode"."LABEL" AS "CREATEDBY_DEPARTMENTID_SOURCEPLACECODE_LABEL", "createdBy_departmentId_sourcePlaceCode"."POSITION" AS "CREATEDBY_DEPARTMENTID_SOURCEPLACECODE_POSITION", "createdBy_departmentId_sourcePlaceCode"."IS_ACTIVE" AS "CREATEDBY_DEPARTMENTID_SOURCEPLACECODE_IS_ACTIVE", "createdBy_departmentId_sourcePlaceCode"."MANDATORY" AS "CREATEDBY_DEPARTMENTID_SOURCEPLACECODE_MANDATORY", "createdBy_departmentId_sourcePlaceCode"."DESCRIPTION" AS "CREATEDBY_DEPARTMENTID_SOURCEPLACECODE_DESCRIPTION", "lastModifiedBy_staff_image"."ID" AS "LASTMODIFIEDBY_STAFF_IMAGE_ID", "lastModifiedBy_staff_image"."LOCATION" AS "LASTMODIFIEDBY_STAFF_IMAGE_LOCATION", "lastModifiedBy_staff_image"."STORAGE_TYPE" AS "LASTMODIFIEDBY_STAFF_IMAGE_STORAGE_TYPE", "lastModifiedBy_staff_office"."ID" AS "LASTMODIFIEDBY_STAFF_OFFICE_ID", "lastModifiedBy_staff_office"."NAME" AS "LASTMODIFIEDBY_STAFF_OFFICE_NAME", "lastModifiedBy_staff_office"."HIERARCHY" AS "LASTMODIFIEDBY_STAFF_OFFICE_HIERARCHY", "lastModifiedBy_staff_office"."EXTERNAL_ID" AS "LASTMODIFIEDBY_STAFF_OFFICE_EXTERNAL_ID", "lastModifiedBy_staff_office"."OPENING_DATE" AS "LASTMODIFIEDBY_STAFF_OFFICE_OPENING_DATE", "lastModifiedBy_departmentId_branch"."ID" AS "LASTMODIFIEDBY_DEPARTMENTID_BRANCH_ID", "lastModifiedBy_departmentId_branch"."NAME" AS "LASTMODIFIEDBY_DEPARTMENTID_BRANCH_NAME", "lastModifiedBy_departmentId_branch"."HIERARCHY" AS "LASTMODIFIEDBY_DEPARTMENTID_BRANCH_HIERARCHY", "lastModifiedBy_departmentId_branch"."EXTERNAL_ID" AS "LASTMODIFIEDBY_DEPARTMENTID_BRANCH_EXTERNAL_ID", "lastModifiedBy_departmentId_branch"."OPENING_DATE" AS "LASTMODIFIEDBY_DEPARTMENTID_BRANCH_OPENING_DATE", "lastModifiedBy_departmentId_sourcePlaceCode"."ID" AS "LASTMODIFIEDBY_DEPARTMENTID_SOURCEPLACECODE_ID", "lastModifiedBy_departmentId_sourcePlaceCode"."LABEL" AS "LASTMODIFIEDBY_DEPARTMENTID_SOURCEPLACECODE_LABEL", "lastModifiedBy_departmentId_sourcePlaceCode"."POSITION" AS "LASTMODIFIEDBY_DEPARTMENTID_SOURCEPLACECODE_POSITION", "lastModifiedBy_departmentId_sourcePlaceCode"."IS_ACTIVE" AS "LASTMODIFIEDBY_DEPARTMENTID_SOURCEPLACECODE_IS_ACTIVE", "lastModifiedBy_departmentId_sourcePlaceCode"."MANDATORY" AS "LASTMODIFIEDBY_DEPARTMENTID_SOURCEPLACECODE_MANDATORY", "lastModifiedBy_departmentId_sourcePlaceCode"."DESCRIPTION" AS "LASTMODIFIEDBY_DEPARTMENTID_SOURCEPLACECODE_DESCRIPTION", "createdBy_departmentId_sourcePlaceCode_code"."ID" AS "CREATEDBY_DEPARTMENTID_SOURCEPLACECODE_CODE_ID", "createdBy_departmentId_sourcePlaceCode_code"."NAME" AS "CREATEDBY_DEPARTMENTID_SOURCEPLACECODE_CODE_NAME", "createdBy_departmentId_sourcePlaceCode_code"."SYSTEM_DEFINED" AS "CREATEDBY_DEPARTMENTID_SOURCEPLACECODE_CODE_SYSTEM_DEFINED", "lastModifiedBy_departmentId_sourcePlaceCode_code"."ID" AS "LASTMODIFIEDBY_DEPARTMENTID_SOURCEPLACECODE_CODE_ID", "lastModifiedBy_departmentId_sourcePlaceCode_code"."NAME" AS "LASTMODIFIEDBY_DEPARTMENTID_SOURCEPLACECODE_CODE_NAME", "lastModifiedBy_departmentId_sourcePlaceCode_code"."SYSTEM_DEFINED" AS "LASTMODIFIEDBY_DEPARTMENTID_SOURCEPLACECODE_CODE_SYSTEM_DEFINED" FROM "ROLE" LEFT OUTER JOIN "APP_USER" AS "createdBy" ON "createdBy"."ROLE" = "ROLE"."ID" LEFT OUTER JOIN "APP_USER" AS "lastModifiedBy" ON "lastModifiedBy"."ROLE" = "ROLE"."ID" LEFT OUTER JOIN "STAFF" AS "createdBy_staff" ON "createdBy_staff"."APP_USER" = "createdBy"."ID" LEFT OUTER JOIN "OFFICE" AS "createdBy_office" ON "createdBy_office"."APP_USER" = "createdBy"."ID" LEFT OUTER JOIN "TELLER" AS "createdBy_tellerId" ON "createdBy_tellerId"."APP_USER" = "createdBy"."ID" LEFT OUTER JOIN "DEPARTMENT" AS "createdBy_departmentId" ON "createdBy_departmentId"."APP_USER" = "createdBy"."ID" LEFT OUTER JOIN "STAFF" AS "lastModifiedBy_staff" ON "lastModifiedBy_staff"."APP_USER" = "lastModifiedBy"."ID" LEFT OUTER JOIN "OFFICE" AS "lastModifiedBy_office" ON "lastModifiedBy_office"."APP_USER" = "lastModifiedBy"."ID" LEFT OUTER JOIN "TELLER" AS "lastModifiedBy_tellerId" ON "lastModifiedBy_tellerId"."APP_USER" = "lastModifiedBy"."ID" LEFT OUTER JOIN "DEPARTMENT" AS "lastModifiedBy_departmentId" ON "lastModifiedBy_departmentId"."APP_USER" = "lastModifiedBy"."ID" LEFT OUTER JOIN "IMAGE" AS "createdBy_staff_image" ON "createdBy_staff_image"."STAFF" = "createdBy_staff"."ID" LEFT OUTER JOIN "OFFICE" AS "createdBy_staff_office" ON "createdBy_staff_office"."STAFF" = "createdBy_staff"."ID" LEFT OUTER JOIN "OFFICE" AS "createdBy_departmentId_branch" ON "createdBy_departmentId_branch"."DEPARTMENT" = "createdBy_departmentId"."ID" LEFT OUTER JOIN "CODE_VALUE" AS "createdBy_departmentId_sourcePlaceCode" ON "createdBy_departmentId_sourcePlaceCode"."DEPARTMENT" = "createdBy_departmentId"."ID" LEFT OUTER JOIN "IMAGE" AS "lastModifiedBy_staff_image" ON "lastModifiedBy_staff_image"."STAFF" = "lastModifiedBy_staff"."ID" LEFT OUTER JOIN "OFFICE" AS "lastModifiedBy_staff_office" ON "lastModifiedBy_staff_office"."STAFF" = "lastModifiedBy_staff"."ID" LEFT OUTER JOIN "OFFICE" AS "lastModifiedBy_departmentId_branch" ON "lastModifiedBy_departmentId_branch"."DEPARTMENT" = "lastModifiedBy_departmentId"."ID" LEFT OUTER JOIN "CODE_VALUE" AS "lastModifiedBy_departmentId_sourcePlaceCode" ON "lastModifiedBy_departmentId_sourcePlaceCode"."DEPARTMENT" = "lastModifiedBy_departmentId"."ID" LEFT OUTER JOIN "CODE" AS "createdBy_departmentId_sourcePlaceCode_code" ON "createdBy_departmentId_sourcePlaceCode_code"."CODE_VALUE" = "createdBy_departmentId_sourcePlaceCode"."ID" LEFT OUTER JOIN "CODE" AS "lastModifiedBy_departmentId_sourcePlaceCode_code" ON "lastModifiedBy_departmentId_sourcePlaceCode_code"."CODE_VALUE" = "lastModifiedBy_departmentId_sourcePlaceCode"."ID" WHERE "ROLE"."APP_USER" = ?]; nested exception is com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-204, SQLSTATE=42704, SQLERRMC=DB2INST1.ROLE, DRIVER=4.21.29


Solution

  • General principles.

    There is no concept of lazy loading in Spring Data JDBC. This is possibly the most important design decision in Spring Data JDBC and it is crucial to understand it:

    Spring Data JDBC will load a complete aggregate, including everything that is referenced by normal Java references. Things that should not or must not be part of the same aggregate must not be referenced by a java reference, but only by id. See Spring Data JDBC, References, and Aggregates for a more in detail discussion of this.

    Projections in the way other Spring Data modules do them, by using an interface as the return value aren't currently supported, but you may use DTOs, i.e. dedicated classes that have a subset of the properties of the entity class, as a return value.

    What is going on in your case.

    AppUser seems to have a reference to a Role which gets loaded by a separate select statement, which is what you are seeing. This select is not controlled by the query in the annotation. Instead the AppUser instance gets initialised by the result from the specified query. Then Spring Data JDBC notes that there are further references and resolves those by the aforementioned SQL statement(s).

    I have no idea why you get an exception. Possibly because the query is to long?

    What you should do

    Create a new class AppUserProjection containing only the fields in your query and us it as your return value. Since there is no reference to Role or other references, no further SQL statments will get executed.

    Even better and more important though, I think your domain model is not suitable for use with Spring Data JDBC. AppUser and Role seem to be two different aggregates and therefore one MUST REFERENCE THE OTHER BY ID. This makes the lazy loading project go away immediately. To navigate from the AppUser to the Role you use the id to load the Role from a separate RoleRepository. This even allows you to implement any caching strategy you want.

    Apart from references you may populate an entity from a SQL query that does not load all properties. All properties not reflected in the SQL will not be set on the entity and will therefore have their respective default value. This is not recommended though, because it creates incomplete entities and any code in your entity class needs to handle possibly missing values, which complicates the code. Use dedicated DTOs instead, as described above.