* 开发中通过pojo传递查询条件,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件
(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
* 需求:根据用户名和用户性别查询用户信息,查询条件放到QueryVo的user属性中。
```
* 查询条件对象 QueryVo
public class QueryVo {
private User user;
public User getUser(){
return user;
}
public void setUser(User user){
this.user = user;
}
}
* IUserDao:持久层接口:
List<User> findUserByVo(QueryVo vo);
* IUserDao.xml:持久层映射配置文件
<!--根据queryVo的条件查询用户-->
<select id="findUserByVo" parameterType="com.itheima.domain.QueryVo" resultType="com.itheima.domain.User">
select * from user where username like #{user.username} AND sex like #{user.sex}
</select>
注意1:这里的parameterType="com.itheima.domain.QueryVo"
所以#{user.username}:user是QueryVo中的user,再用OGNL表达式user.username得到username
* MybatisTest:测试类:
@Test
public void testFindUserByVo(){
QueryVo vo = new QueryVo();
User user = new User();
user.setUsername("%王%");
user.setSex("男");
vo.setUser(user);
List<User> users = userDao.findUserByVo(vo);
for (User user1 : users) {
System.out.println(user1);
}
}
注意2:
```
2.3 测试模糊查询FindByName()
2.3.1 代码实现
```
* IUserDao:持久层接口:
List<User> findByName(String userName);
* IUserDao.xml:持久层映射配置文件
<select id="findByName" parameterType="String" resultType="com.itheima.domain.User">
<!--select * from user where username like '%${value}%'--!>
select * from user where username like #{name};
</select>
* MybatisTest:测试类:
@Test
public void testFindByName(){
//List<User> users = userDao.findByName("王");
List<User> users = users = userDao.findByName("%王%");
for (User user : users) {
System.out.println(user);
}
}
```
2.3.2 注意:占位符和sql拼接 : #{}和${}
* IUserDao.xml:持久层映射配置文件
写法1:select * from user where username like #{name};
写法2:select * from user where username like '%${value}%';
写法2的话,只能是固定写法${value},因为源码中指定了读取的key的名字就是“value”,所以我们在绑定参数时,只能叫做value
* 几种情况
情况1:'%${value}%' sql语句拼接
IUserDao.xml:select * from user where username like '%${value}%'
testFindByName():userDao.findByName("王");
最终的得到的SQL:
* select * from user where username like '%王%';
Preparing: select * from user where username like '%王%';
Parameters: (什么都没)
这个用的是Statement对象的字符串的拼接来实现,直接将参数拼上去
情况2:#{name}; 占位符
IUserDao.xml:select * from user where username like #{name};
testFindByName():users = userDao.findByName("%王%");
最终的得到的SQL:
* select * from user where username like ?;
Preparing: select * from user where username like ?;
Parameters: %王%(String)
这个用的是PrepareStatement参数占位符-------显然带有预处理的方式要更好,实际开发用的更多。
情况2:这是错的
IUserDao.xml:select * from user where username like '%${value}%'
testFindByName():users = userDao.findByName("%王%");
最终的得到的SQL:
* select * from user where username like '%%王%%';
2.4 测试更新操作 updateUser
2.4.1 代码实现
```
* IUserDao:持久层接口:
void updateUser(User user);
* IUserDao.xml:持久层映射配置文件
<update id="updateUser" parameterType="user">
update user set username=#{username}, address=#{address}, sex=#{sex}, birthday=#{birthday} where id=#{id};
</update>
* MybatisTest:测试类:
@Test
public void testUpdate(){
User user = new User();
user.setId(61);
user.setUsername("mybatis Update user");
user.setAddress("北京市顺义区");
user.setSex("女"); //数据库中是一个字符
user.setBirthday(new Date());
//执行更新方法
userDao.updateUser(user);
}
```
2.5 测试删除操作 deleteUser(通过用户id删除)
```
* IUserDao:持久层接口
void deleteUser(Integer userId);
* IUserDao.xml:持久层映射配置文件
<!--
parameterType:int/INT/Integer/INTEGER/java.lang.Integer都可以,为什么支持这么多写法呢?
因为mybatis中使用了别名,我们也可以在主配置文件中用<typeAliases>标签配置别名
而且别名不区分大小写
思考:当参数传递是一个基本类型/基本类型的包装类时,且参数只有一个时,这个参数形式可以随意写:uid/id/user_id...
parameterType 参数的类型要和IUserDao中的参数类型对应上。
-->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id = #{uid};
</delete>
* MybatisTest:测试类:
@Test
public void testDelete(){
userDao.deleteUser(53);
}
```
2.6 测试根据ID查询一个 findById
```
* IUserDao:持久层接口
User findById(Integer userId);
* IUserDao.xml:持久层映射配置文件
<select id="findById" parameterType="INT" resultType="com.itheima.domain.User">
select * from user where id = #{id};
</select>
* MybatisTest:测试类:
@Test
public void testFindOne(){
//执行查询一个方法
User user = userDao.findById(48);
System.out.println(user);
}
```
2.7 Mybatis的输出结果封装
2.7.1 实体类中的属性名称必须和查询语句中的列名保持一致
windows mysql数据库不区分大小写
linux中的mysql是严格区分大小写
实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装。
当我们使用查询的结果进行封装时,要求我们的实体类必须和数据库的类名保持一致。
```
* 实体类:User
public class User implements Serializable {
private Integer UserId;
private String userName;
private String userAddress;
private String userSex;
private Date useBirthday;
}
* MySql:
id
username
birthday
sex
address
```
2.7.2 解决方法1:使用别名
* 实体类:User
public class User implements Serializable {
private Integer userId;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress;
}
* MySql:
id
username
birthday
sex
address
* IUserDao.xml
<insert id="saveUser" parameterType="User">
insert into user(username, address, sex, birthday) values (#{useNname},#{userAddresss},#{userSex},#{useBirthday});
</insert>
这样是无法将结果集进行封装的,不满足实体类中的属性名称和查询语句中的列名保持一致
* 解决方法:使用别名
```
<select id="findAll" resultType="com.itheima.domain.User">
select id as userID,username as userName,address as userAddress,sex as userSex,
birthday as useBirthday from user;
</select>
这种解决方式的执行效率是最高的,因为是在sql语句层面就解决了。
```