mybatisjava-17oracle19cspring-mybatis

MyBatis seelct query with where condition list of objects


Employee Class Long id: String Name;

I have list of Employee object and i need to get the details from Employee table filtered with both id and name.

I tried something like this

<resultMap type="EmployeeDetails" id="EmployeeDetailMap">
        <result property="employeeId" column="EMPLOYEE_ID"/>
        <result property="employeeName" column="EMPLOYEE_NAME"/>        
    </resultMap>

<select id="getEmployeeDetails" resultMap="EmployeeDetailMap">
   <foreach collection="employeeList" item="employee" index="index" close=";" separator=";">
   SELECT * FROM EMPLOYEE WHERE TRUNC(EFFECTIVE_DT)=TRUNC(SYSDATE) AND EMPLOYEE_ID = #{employee.employeeId} AND EMPLOYEE_NAME = #{employee.employeeName}
    </foreach>
</select>

And getting error like

Cause: java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended

QUERY that is generated is

SELECT * FROM EMPLOYEE  WHERE TRUNC(EFFECTIVE_DT)=TRUNC(SYSDATE) AND EMPLOYEE_ID = ? AND EMPLOYEE_NAME = ?;SELECT * FROM EMPLOYEE  WHERE TRUNC(EFFECTIVE_DT)=TRUNC(SYSDATE) AND EMPLOYEE_ID = ? AND EMPLOYEE_NAME = ?;

Solution

  • Oracle does not allow multiple SQL statements in a single command (as this is a common method of creating SQL injection attacks). Instead, generate a single query; maybe something like:

    <select id="getEmployeeDetails" resultMap="EmployeeDetailMap">
       SELECT *
       FROM   EMPLOYEE
       WHERE  EFFECTIVE_DT >= TRUNC(SYSDATE)
       AND    EFFECTIVE_DT <  TRUNC(SYSDATE) + INTERVAL '1' DAY
       AND    (EMPLOYEE_ID, EMPLOYEE_NAME) IN (
                <foreach collection="employeeList" item="employee" index="index" close="" separator=",">
                (#{employee.employeeId}, #{employee.employeeName})
                </foreach>
              )
    </select>
    

    Note: Untested as I do not have MyBatis or your tables/data, but you should get the general idea and can correct any syntax errors.

    Note 2: Filtering EFFECTIVE_DT on a range allows Oracle to use an index on the column; if you filter on TRUNC(EFFECTIVE_DT) then Oracle cannot use an index and would require a separate function-based index.