package com.lonelyWolf.mybatis;
import com.alibaba.fastjson.JSONObject;
import com.lonelyWolf.mybatis.mapper.UserMapper;
import com.lonelyWolf.mybatis.model.LwUser;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MyBatisQueryByParam {
public static void main(String[] args) throws IOException {
String resource = “mybatis-config.xml”;
//读取mybatis-config配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//创建SqlSession对象
SqlSession session = sqlSessionFactory.openSession();
/**
* 相比较于session.selectList("com.xxx.UserMapper.listAllUser")来实现查询,
* 下面这种通过先获取mapper再挑用mapper中方法的方式会更灵活
*/
UserMapper userMapper = session.getMapper(UserMapper.class);
List<LwUser> userList = userMapper.listUserByUserName("孤狼1号");
System.out.println(null == userList ? "": JSONObject.toJSONString(userList));
List<LwUser> userList2 = userMapper.listUserByTable("lw_user");
System.out.println(null == userList2 ? "": JSONObject.toJSONString(userList2));
}
}
查询结果输出如下:
![image](https://upload-images.jianshu.io/upload_images/24613101-5ee784012816a63c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
## #和$区别
从上面的输出sql语句截图可以看到,如果使用#的话,那么sql语句会先在sql语句中使用占位符,也就是预编译,对应JBDC中的PreparedStatement。而使用$,则会直接把参数拼到sql语句上,相当于JDBC中的Statement。
一般情况下不建议使用$,因为这种直接拼接的方式容易被sql注入攻击。 比如,上面的sql语句:
select user_id,user_name from ${tableName}
假如tableName传入的是:lw_user;delete from lw_user;那么这时候执行的sql语句就会变成:
select user_id,user_name from lw_user;delete from lw_user;
这时候整张表的数据都会被删除,而如果使用的是#{tableName},最终执行的是如下sql:
select user_id,user_name from ‘lw_user;delete from lw_user;’
产生的后果只是查询了一张不存在的表而已。
## 动态参数的查询
上面的例子中参数是固定的,那么假如我们参数不固定呢?比如有2个参数,但是我可能一个都不用,也可能只用1个,或者2个都用。这种又该如何实现呢? 如下图所示,可以通过where和if标签结合使用,两个条件都写了and,这是因为Mybatis会帮我们处理掉多余的and关键字。
select user_id,user_name from lw_user and user_id=#{userId} and user_name=#{userName}
或者说我们对同一个参数需要进行不同取值拼接不同的sql,那么可以通过choose标签根据不同的参数拼接不同的sql
select user_id,user_name from lw_user
and user_id=#{userId}
and user_id=#{userId}
and user_id=#{userId}
当然,Mybatis还提供了其他许多标签,用来处理更加复杂的组合,在这里就不举例说明了。
## 一对一查询
假如我们现在有两种表,是一对一关系,我们想同时查询出来,当然最简单的办法是再写一个类,把两张表的结果属性都放到一个类里面,但是这种方式无疑会造成了很多重复代码,而且体现不出层级关系,假如我们有一张表lw_user表,存储用户信息,另一张表lw_user_job存储了用户的工作经历,那么很明显,job对应类应该包含在user类内,这种应该怎么实现呢?
请看!
1、新建一个实体类UserJob来映射lw_user_job表属性:
package com.lonelyWolf.mybatis.model;
public class LwUserJob {
private String id;
private String userId; //用户id
private String companyName; //公司名
private String position; //职位
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}
2、在原先的LwUser类增加一个引用属性来引用LwUserJob:
package com.lonelyWolf.mybatis.model;
public class LwUser {
private String userId; //用户id
private String userName; //用户名称
private LwUserJob usreJobInfo;//用户工作信息
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public LwUserJob getUsreJobInfo() {
return usreJobInfo;
}
public void setUsreJobInfo(LwUserJob usreJobInfo) {
this.usreJobInfo = usreJobInfo;
}
}
3、UserMapper.java中新增一个方法:
List listUserAndJob();
这时候UserMapper.xml需要自定义一个ResultMap:
select * from lw_user u inner join lw_user_job j on u.user_id=j.user_id