Mybatis搞三下(参数的深入理解&模糊查询)
上篇我们详细了解了Mapper文件里的namespace、各种CRUD语句的解析和执行过程,本篇详解这些和java程序连接的mapper文件里的参数调用(偏实战)。
CRUD语句
select
选择,查询语句;
- id : 就是对应的namespace中的方法名;
- resultType:Sql语句执行的返回值!
- parameterType : 参数类型!
-
编写接口
//根据ID查询用户 User getUserById(int id);
-
编写对应的mapper中的sql语句
<select id="getUserById" parameterType="int" resultType="com.feng.pojo.User"> select * from mybatis.user where id = #{ id} </select>
-
测试
@Test public void getUserById() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.getUserById(1); System.out.println(user); sqlSession.close(); }
Insert
<!--对象中的属性,可以直接取出来-->
<insert id="addUser" parameterType="com.feng.pojo.User">
insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd});
</insert>
update
<update id="updateUser" parameterType="com.feng.pojo.User">
update mybatis.user set name=#{name},pwd=#{pwd} where id = #{id} ;
</update>
Delete
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id = #{id};
</delete>
注意点:
- 增删改需要提交事务!
parameterType
传入参数类型
<select id="getUserById" parameterType="int" resultType="com.feng.pojo.User">
select * from mybatis.user where id = #{id}
</select>
- 写在mapper文件中的一 个属性。表示dao接口中方法的参数数据类型。
- 这个属性是可选的(mybatis里反射能拿到接口参数类型)
(基本数据类型:int,string,long,Date; 复杂数据类型:类和Map)
如何获取参数中的值?
基本数据类型:#{value}或${value} 获取参数中的值
复杂数据类型:#{属性名}或KaTeX parse error: Expected 'EOF', got '#' at position 14: {属性名} ,map中则是#̲{key}或{key}
注:#{}与${}的区别:
#{value}:输入参数的占位符,相当于jdbc的? 防注入 自动添加了‘ ’ 引号!
例如:select * from user where username = #{name} //输入的参数xiaoming,就会自动加上引号
变成:select * from user where username = ‘xiaoming’
注意:value可以写任意变量,没有统一规定
v a l u e : 不 防 注 入 , 就 是 字 符 串 拼 接 例 如 : s e l e c t ∗ f r o m u s e r w h e r e u s e r n a m e l i k e ′ {value}: 不防注入,就是字符串拼接 例如:select * from user where username like '% value:不防注入,就是字符串拼接例如:select∗fromuserwhereusernamelike′{value}%’ //默认不加引号
注意:只能写value!!!
select * FROM user WHERE username like “%”‘s’"%"//是正确的,符合语法,引号的形式只能是这样,不能变!
#{}更安全,优先考虑,${}还用于properties文件中的变量占位符
#{} | ${} | |
---|---|---|
意义 | 占位符 | 拼接字符串(properties中占位符) |
参数类型 | 简单类型、pojo属性值 | 简单类型,pojo属性值(如果传输单个简单类型或者字符串类型值,${}括号中只能写value) |
解析 | 解析时参数带引号,解析为JDBC预编译语句的参数占位符 | 纯粹的String替换,解析不带引号,动态SQL解析会进行变量替换 |
安全 | 防止SQL注入 | 存在SQL注入风险 |
用处 | 一般用于传递用户输入值(不确定) | 一般用于传递确定值(开发人员确定的值) |
resultType
输出结果集就两种,基本数据类型或者pojo类型
注意这里不管查询返回的是list还是map或者array,亦或者是单个User(pojo)对象,resultType都要写成user(pojo)
返回java对象
<select id="getUserById" parameterType="int" resultType="com.feng.pojo.User">
select * from mybatis.user where id = #{id}
</select>
返回java类型
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id = #{id};
</delete>
resultMap(常用)
resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
这里的resultMap如果使用,需要在UserMapper.xml配置
<resultMap id="UserMap" type="User">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
<select id="getUserByRowBounds" resultMap="UserMap">
select * from mybatis.user
</select>
接口
//分页1
List<User> getUserByLimit(Map<String,Integer> map);
//分页2
List<User> getUserByRowBounds();
测试
@Test
public void getUserByLimit(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("startIndex",1);
map.put("pageSize",2);
List<User> userList = mapper.getUserByLimit(map);
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
@Test
public void getUserByRowBounds(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
//RowBounds实现
RowBounds rowBounds = new RowBounds(1, 2);
//通过Java代码层面实现分页
List<User> userList = sqlSession.selectList("com.feng.dao.UserMapper.getUserByRowBounds",null,rowBounds);
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
resultMap
元素是 MyBatis 中最重要最强大的元素- ResultMap 的设计思想是,对于简单的语句根本不需要配置显式的结果映射,而对于复杂一点的语句只需要描述它们的关系就行了。
ResultMap
最优秀的地方在于,虽然你已经对它相当了解了,但是根本就不需要显式地用到他们。
其实不难发现,这个resultMap就是为了解决属性名和字段名不一致的问题。
模糊查询,like
mapper
<select id="getUserLike" resultType="com.feng.pojo.User">
select * from mybatis.user where name like "%"#{value}"%"
</select>
test
@Test
public void getUserLike(){
//模糊查询
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.getUserLike("%李%");
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
可以看到这里like后面已经拼接完成了
(这里使用了log4j日志打印信息)
log4j配置
在pom文件中添加log4j依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
在resources中添加log4j.properties
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/feng.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
在mybatis-config.xml中添加
<settings>
<!-- <setting name="logImpl" value="STDOUT_LOGGING"/>-->
<setting name="logImpl" value="LOG4J"/>
</settings>
运行即可
具体代码
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="*****"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/feng/dao/UserMapper.xml"/>
</mappers>
</configuration>
User.java
package com.feng.pojo;
//实体类
public class User {
private int id;
private String name;
private String pwd;
public User() {
}
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
pom.xml部分
<!--在build中配置resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
UserMapper.java
package com.feng.dao;
import com.feng.pojo.User;
import java.util.List;
import java.util.Map;
public interface UserMapper {
List<User> getUserLike(String value);
//查询全部用户
List<User> getUserList();
//根据ID查询用户
User getUserById(int id);
User getUserById2(Map<String,Object> map);
//insert一个用户
int addUser(User user);
int addUser2(Map<String,Object> map);
//update一个用户
int updateUser(User user);
//Delete一个用户
int deleteUser(int id);
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.feng.dao.UserMapper">
<select id="getUserLike" resultType="com.feng.pojo.User">
select * from mybatis.user where name like "%"#{value}"%"
</select>
<select id="getUserList" resultType="com.feng.pojo.User">
select * from mybatis.user
</select>
<select id="getUserById" parameterType="int" resultType="com.feng.pojo.User">
select * from mybatis.user where id = #{id}
</select>
<select id="getUserById2" parameterType="map" resultType="com.feng.pojo.User">
select * from mybatis.user where id = #{helloId} and name=#{name}
</select>
<insert id="addUser" parameterType="com.feng.pojo.User" >
insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd});
</insert>
<insert id="addUser2" parameterType="map" >
insert into mybatis.user (id,pwd) values (#{userid},#{password});
</insert>
<update id="updateUser" parameterType="com.feng.pojo.User">
update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id};
</update>
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id = #{id};
</delete>
</mapper>
MybatisUtil.java
package com.feng.utils;
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;
//sqlSessionFactory --> sqlSession
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//使用Mybatis第一步:获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//既然有了 SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了。
// SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
}
UserMapperTest.java
package com.feng.dao;
import com.feng.pojo.User;
import com.feng.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class UserMapperTest {
@Test
public void getUserLike(){
//模糊查询
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.getUserLike("%李%");
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
@Test
public void test() {
//第一步:获得SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
//方式一:getMapper
UserMapper UserMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = UserMapper.getUserList();
//方式二:
//List<User> userList = sqlSession.selectList("com.feng.dao.UserDao.getUserList");
for (User user : userList) {
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭SqlSession
sqlSession.close();
}
}
//根据id查询用户
@Test
public void getUserById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUserById(1);
System.out.println(user);
sqlSession.close();
}
@Test
public void getUserById2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<String, Object>();
map.put("helloId", 1);
mapper.getUserById2(map);
for (String key : map.keySet()) {
System.out.println("key= "+ key + " and value= " + map.get(key));
}
sqlSession.close();
}
//增删改查需要提交事务
@Test
public void addUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int res = mapper.addUser(new User(6, "小仙", "222255"));
if (res > 0) {
System.out.println("插入成功");
}
//提交事务
sqlSession.commit();
sqlSession.close();
}
@Test
public void addUser2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<String, Object>();
map.put("userid",7);
map.put("password","546552");
mapper.addUser2(map);
sqlSession.commit();
sqlSession.close();
}
@Test
public void updateUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int res = mapper.updateUser(new User(6, "小小仙", "222222"));
if (res > 0) {
System.out.println("修改成功");
}
//提交事务
sqlSession.commit();
sqlSession.close();
}
@Test
public void deleteUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int res = mapper.deleteUser(6);
if (res > 0) {
System.out.println("删除成功");
}
//提交事务
sqlSession.commit();
sqlSession.close();
}
}