传入参数
由于mybatis底层还是JDBC,而JDBC在操作数据库传递参数时,有两种方式,一种是使用Statement,还有一种是使用PreparedStatement:使用statement时,存在SQL注入问题,PreparedStatement则通过预编译解决了SQL注入问题。
在mybatis中,引入参数有两种方式,一种是使用#,还有一种是使用$,其中,使用#对应了JDBC中的PreparedStatement,而使用 $ 则对应了JDBC中的Statement,因此在mybatis中,推荐使用#。
#和$的使用
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sxt</groupId>
<artifactId>mybatis-08-param</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.27</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
</project>
实体类
接口
映射文件
<?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.sxt.dao.IUserDao">
<delete id="delete1" parameterType="int">
<!-- # 是预编译 也就是通过PreparedStatement方式实现的 -->
delete from t_user where id=#{id}
</delete>
<delete id="delete2" parameterType="int">
<!-- $ 是直接赋值 也就是通过Statement 方式实现的 有SQL注入风险 而且在接口中需要通过@Param注解指定key -->
delete from t_user where id=${id}
</delete>
<insert id="insert1">
insert into t_user(username,password)
values(#{arg0},#{arg1})
</insert>
<insert id="insert2">
insert into t_user(username,password)
values(#{param1},#{param2})
</insert>
<insert id="insert3">
insert into t_user(username,password)
values(#{name},#{password})
</insert>
<insert id="addUser" parameterType="UserDto">
insert
into
t_user
(
username
,password
,age
,address
)values(
#{user.username}
,#{user.password}
,#{age}
,#{address}
)
</insert>
</mapper>
测试
package com.sxt.test;
import static org.junit.Assert.*;
import java.io.IOException;
import java.io.InputStream;
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 org.junit.Test;
import com.sxt.dao.IUserDao;
import com.sxt.pojo.User;
import com.sxt.pojo.UserDto;
public class TestDemo {
@Test
public void test1() throws IOException {
// 通过resources对象加兹安配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 获取SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 通过SqlSessionFactory对象获取SqlSession对象
SqlSession session = factory.openSession();
IUserDao dao = session.getMapper(IUserDao.class);
int i = dao.delete2(34);
System.out.println("影响的行数:"+i);
session.commit();
session.close();
}
@Test
public void test2() throws IOException {
// 通过resources对象加兹安配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 获取SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 通过SqlSessionFactory对象获取SqlSession对象
SqlSession session = factory.openSession();
IUserDao dao = session.getMapper(IUserDao.class);
dao.insert3("zhans", "123");
session.commit();
session.close();
}
/**
* 包装类 通过存取器 "." 处理
* @throws IOException
*/
@org.junit.Test
public void test3() throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = factory.openSession();
IUserDao dao = session.getMapper(IUserDao.class);
User user = new User();
user.setUsername("admin111");
user.setPassword("123");
UserDto dto = new UserDto();
dto.setUser(user);
dto.setAge(18);
dto.setAddress("固戍");
dao.addUser(dto);
session.commit();
session.close();
}
}
推荐使用#方式
多个参数
如果Mapper接口中有多个参数,无论参数名是什么,在Mapper.xml文件中,参数都是arg0、arg1…或者param1、param2…
如果非要使用自己的参数名,可以通过@Param注解自定义
返回数据
ResultType
对于简单数据类型,例如查询总记录数、查询某一个用户名这一类返回值是一个基本数据类型的,直接写Java中的基本数据类型即可。
如果返回的是一个对象或者集合,并且对象中的属性和查询的字段名是一一对应的,那么resultType也可以直接写一个对象。
ResultMap
resultMap主要用来解决属性名和字段名不一致以及一对多、一对一查询等问题 字段名不一致时,首先可以通过取别名解决,例如Bean的定义如下:
映射文件
<?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.sxt.dao.IUserDao">
<select id="query1" resultType="User">
select
id
,username name
,password
from t_user
</select>
<!-- 定义一个ResultMap -->
<resultMap type="User" id="BaseResultMap">
<!-- 定义成员变量和字段的映射关系 -->
<id property="id" column="id"/>
<result property="name" column="username" />
<result property="password" column="password"/>
</resultMap>
<select id="query2" resultMap="BaseResultMap">
select
*
from t_user
</select>
<insert id="insert1" parameterType="User"
useGeneratedKeys="true" keyProperty="id">
insert into t_user(username,password)values(#{name},#{password})
</insert>
<insert id="insert2" parameterType="User">
<selectKey keyProperty="id" resultType="int" >
select LAST_INSERT_ID()
</selectKey>
insert into t_user(id,username,password)values(#{id},#{name},#{password})
</insert>
</mapper>
测试
package com.sxt.test;
import static org.junit.Assert.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
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 org.junit.Test;
import com.sxt.dao.IUserDao;
import com.sxt.pojo.User;
import com.sxt.pojo.UserDto;
public class TestDemo {
@Test
public void test1() throws IOException {
// 通过resources对象加兹安配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 获取SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 通过SqlSessionFactory对象获取SqlSession对象
SqlSession session = factory.openSession();
IUserDao dao = session.getMapper(IUserDao.class);
List<User> list = dao.query1();
for (User user : list) {
System.out.println(user);
}
session.commit();
session.close();
}
@Test
public void test2() throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = factory.openSession();
IUserDao dao = session.getMapper(IUserDao.class);
User user = new User();
user.setName("qwer");
user.setPassword("dfa");
dao.insert1(user);
System.out.println("------->"+user.getId());
session.commit();
session.close();
}
}
主键回写
一般情况下,主键有两种生成方式:
- 主键自增长
- 自定义主键(一般可以使用UUID)
如果是第二种,主键一般是在Java代码中生成,然后传入数据库执行,如果是第一个主键自增长,此时,Java可能需要知道数据添加成功后的主键。 在MyBatis中,可以通过主键回填来解决这个问题(推荐)。
主键回填
<!--
useGeneratedKeys:使用生成的主键
keyProperty="id":将生成的主键的值保存到对象的id属性中
-->
<insert id="addEmp" parameterType="emp"
useGeneratedKeys="true" keyProperty="id">
insert into t_emp(name,age)values(#{name},#{age})
</insert>
selectKey
另外,可以利用MySQL自带的last_insert_id()函数查询刚刚插入的id