“This is the 22nd day of my participation in the First Challenge 2022. For details: First Challenge 2022”
A, select
Query statements are one of the most commonly used elements in MyBatis – just storing data in the database is not valuable, but it can be retrieved, and most applications are more frequently query than modify. One of the basic principles of MyBatis is that it is common to perform multiple queries between each insert, update, or delete operation. Therefore, MyBatis has made quite a few improvements in query and result mapping. The SELECT element of a simple query is very simple. The SELECT element allows you to configure a number of properties to configure the behavior details of each statement.
attribute | describe |
---|---|
id |
A unique identifier in the namespace that can be used to refer to this statement. |
parameterType |
The class-fully qualified name or alias that will be passed for the argument to this statement. This property is optional because MyBatis can infer the parameters of a specific incoming statement through the TypeHandler, which defaults to unset. |
resultType |
The fully qualified name or alias of the class that is expected to return a result from this statement. Note that if a collection is returned, it should be set to the type contained in the collection, not the type of the collection itself. Only one resultType and resultMap can be used simultaneously. |
resultMap |
Named reference to an external resultMap. Result mapping is the most powerful feature of MyBatis. If you understand it well, many complex mapping problems can be solved easily. Only one resultType and resultMap can be used simultaneously. |
flushCache |
Setting this to true causes the local and secondary caches to be cleared whenever a statement is called. Default: false. |
useCache |
Setting it to true will cause the results of this statement to be cached by the second level cache. Default: true for select elements. |
timeout |
This setting is the number of seconds the driver waits for the database to return the result of the request before throwing an exception. The default is unset (database driven). |
fetchSize |
This is a recommended value for drivers to try to make the number of rows returned per batch equal to this value. The default value is unset (dependent driver). |
statementType |
The value can be STATEMENT, PREPARED or CALLABLE. This will make MyBatis use Statement, PreparedStatement, or CallableStatement, respectively. The default value is PREPARED. |
resultSetType |
FORWARD_ONLY, SCROLL_SENSITIVE, SCROLL_INSENSITIVE, or one of DEFAULT (equivalent to unset), which defaults to unset (database driver dependent). |
databaseId |
If databaseIdProvider is configured, MyBatis will load all statements that do not have a databaseId or match the current databaseId. If both tagged and untagged statements are present, untagged statements are ignored. |
resultOrdered |
This setting applies only to nested result SELECT statements: if true, nested result sets or groups are assumed to be included, and no references to previous result sets are generated when a primary result row is returned. This keeps memory from running out when retrieving nested result sets. Default value:false . |
resultSets |
This setting only works with multiple result sets. It lists the result sets returned after statement execution and gives each result set a name, separated by commas. |
Parameter passing
One or more parameters may be passed in a query statement according to different query conditions. How to obtain these parameters?
There are four cases of parameter passing
A single parameter
: Accepts values of primitive types, object types, and collection types. If there is only one parameter, MyBatis can use this parameter directly without any processing.- Multiple parameters: Any multiple parameters will be repackaged by MyBatis into a Map. The Map key is param1, param2, 0, and 1. The Map value is the parameter value, which can be obtained by key
Named parameters
MyBatis will encapsulate the parameters into the Map using the specified name using the @param annotationPOJO
: If the parameter belongs to a service POJO, the POJO is directly passedMap
: You can also encapsulate multiple parameters as a Map and pass the Map directly
Passing multiple parameters
Add a query method to the EmployeeDao interface
Employee getEmpByIdAndEmpName(Integer id, String empName);
Copy the code
Add SQL mappings to employee.xml
<select id="getEmpByIdAndEmpName" resultType="com.citi.entity.Employee">
select * from t_employee where id = #{id} and empname = #{empName}
</select>
Copy the code
Execute test method
Modifying SQL statements
<select id="getEmpByIdAndEmpName" resultType="com.citi.entity.Employee">
select * from t_employee where id = #{param1} and empname = #{param2}
</select>
Copy the code
Run the test again
When only one argument is passed, as in the getEmpById method, the name of the passed argument can be arbitrary
<select id="getEmpById" resultType="com.citi.entity.Employee">
select * from t_employee where id = #{mybatis}
</select>
Copy the code
Perform the test
I’ll just pass in an argument, write whatever name you want
#{parameter name} is invalid. You can use 0, 1, param1, param2 instead, because MyBatis automatically encapsulates multiple parameters in the Map. The Map used for encapsulation can be the index of the parameter
You can use the @param annotation to specify keys that are encapsulated in a Map. Modify the method definition to specify the name of the key encapsulated in MyBatis
Employee getEmpByIdAndEmpName(@Param("id") Integer id, @Param("name") String empName);
Copy the code
Use #{parameter name} values in SQL mapping files to perform tests
Introduced to the Map
Add a method to the EmoloyeeDao interface
Employee getEmployeeByIdAndName(Map<String,Object> paramMap);
Copy the code
Add SQL mapping statements
<select id="getEmployeeByIdAndName" resultType="com.citi.entity.Employee">
select * from t_employee where id = #{id} and empname = #{name}
</select>
Copy the code
Add test methods
@Test
public void getEmployeeByIdAndName(a){
EmployeeDao employeeDao = openSession.getMapper(EmployeeDao.class);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("id".1);
paramMap.put("name"."stark");
Employee employee = employeeDao.getEmployeeByIdAndName(paramMap);
System.out.println(employee);
}
Copy the code
Perform the test
When a parameter is passed into a Map, you can use #{Key} to get the Value of the parameter.
When you have all of these cases in a method, that is, multiple arguments
getByIdAndNameAndEmployee(@Param("id) id, String empName, Employee employee);
Copy the code
Id is set to #{id}. EmpName is set to #{param2}. Email is set to #{param3.email
Processing parameters
SQL statement parameter positions in SQL mapping files support properties such as javaType, jdbcType, Mode, numericScale, resultMap, typeHandler, and jdbcTypeName
jdbcType
The argument can also specify a special data type
#{property,javaType=int,jdbcType=NUMERIC}
#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
Copy the code
- JavaType can usually be determined from the parameter object
- If NULL is passed as a value, the jdbcType needs to be set for all columns that may be empty
- For numeric types, you can set the number of digits reserved after the decimal point
<select id="getEmpByIdAndEmpName" resultType="com.citi.entity.Employee">
select * from t_employee where id = #{id,jdbcType=INTEGER} and empname = #{name}
</select>
Copy the code
# {} and ${}
To get the value of a parameter, use #{} or ${}.
- #{key} : precompile to SQL, safer
- ${key} : concatenate SQL, there will be SQL injection vulnerability
Modify getEmployeeByIdAndEmpName method corresponding SQL statements, use ${}
<select id="getEmpByIdAndEmpName" resultType="com.citi.entity.Employee">
select * from t_employee where id = ${id} and empname = #{name}
</select>
Copy the code
Id =1 is directly concatenated to SQL
Only parameter positions in SQL statements are supported for precompilation. ${} can be used to pass table names dynamically
Modify the getEmployeeByIdAndName test method, and add the table name information to the paramMap
@Test
public void getEmployeeByIdAndName(a){
EmployeeDao employeeDao = openSession.getMapper(EmployeeDao.class);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("id".1);
paramMap.put("name"."stark");
paramMap.put("tableName"."t_employee");
Employee employee = employeeDao.getEmployeeByIdAndName(paramMap);
System.out.println(employee);
}
Copy the code
Modify the mapping SQL for getEmployeeByIdAndName with ${tableName} to get the tableName
<select id="getEmployeeByIdAndName" resultType="com.citi.entity.Employee">
select * from ${tableName} where id = #{id} and empname = #{name}
</select>
Copy the code
Perform the test
If you use #{} to pass the tableName, change the mapping SQL for getEmployeeByIdAndName, use #{tableName} to get the tableName, and run the test again
Error: Only parameter positions in SQL statement are supported for precompilation
Query returns List
The getAllEmployees method is added to the EmployeeDao interface to query all employees
List<Employee> getAllEmployees(a);
Copy the code
Employee.xml adds mapping SQL
<! ResultType specifies the type of the element in the collection.
<select id="getAllEmployees" resultType="com.citi.entity.Employee">
select * from t_employee
</select>
Copy the code
Add test methods
@Test
public void getAllEmployees(a){
EmployeeDao employeeDao = openSession.getMapper(EmployeeDao.class);
List<Employee> employeeList = employeeDao.getAllEmployees();
for(Employee employee : employeeList) { System.out.println(employee); }}Copy the code
Execute the test method
The query results are encapsulated into a Map
The query returns a single record with the following name as Key and the Value as Value
The new method
Map<String, Object> getEmployeeByIdWithMap(Integer id);
Copy the code
Add an SQL mapping statement. Because the data returned is of Map type, the resultType is Map
<select id="getEmployeeByIdWithMap" resultType="map">
select * from t_employee where id = #{id}
</select>
Copy the code
Add test methods
@Test
public void getEmployeeByIdWithMap(a){
EmployeeDao employeeDao = openSession.getMapper(EmployeeDao.class);
Map<String, Object> employeeMap = employeeDao.getEmployeeByIdWithMap(1);
System.out.println(employeeMap);
}
Copy the code
Perform the testBy default, a Map encapsulates the column name as the Key and the Value as the Value
If multiple records are returned, they are encapsulated into a Map
Define methods
Map<Integer, Employee> getAllEmployeesWithMap(a);
Copy the code
Add SQL mapping statements to employee.xml
<select id="getAllEmployeesWithMap" resultType="map">
select * from t_employee
</select>
Copy the code
Add test methods
@Test
public void getAllEmployeesWithMap(a){
EmployeeDao employeeDao = openSession.getMapper(EmployeeDao.class);
Map<Integer, Employee> employeeMap = employeeDao.getAllEmployeesWithMap();
System.out.println(employeeMap);
}
Copy the code
Perform the test
will
Add a primary key definition using @mapkey to specify the primary key of a Map
@MapKey("id")
Map<Integer, Employee> getAllEmployeesWithMap(a);
Copy the code
Run the test again
Print out the attributes of the element with key 1 in the test method and add code to the getAllEmployeesWithMap test method
@Test
public void getAllEmployeesWithMap(a){
EmployeeDao employeeDao = openSession.getMapper(EmployeeDao.class);
Map<Integer, Employee> employeeMap = employeeDao.getAllEmployeesWithMap();
System.out.println(employeeMap);
Employee employee = employeeMap.get(1);
System.out.println(employee.getEmpName());
}
Copy the code
A cast exception has occurredThis error occurs because the resultType defined in the SQL mapping statement is Map, so the resultType type in the SQL mapping statement is changed to the type of the element in the collection
<select id="getAllEmployeesWithMap" resultType="com.citi.entity.Employee">
select * from t_employee
</select>
Copy the code
The test again
Query multiple data returns a Map, resultType is the type of the element stored in the set Value