1. Mybatis的增删改查
使用基于动态代理的方式编写dao
- 操作步骤
1.创建工程导入坐标
2.创建mybatis的核心配置文件
3.创建sql映射文件
4.编写dao接口和接口中的方法
5.编写sql语句
1 UserDao接口
public interface UserDao {
//保存用户
void save(User user);
//根据id更新用户
void update(User user);
//根据id删除用户
void delete(int id);
//查询所有用户
List<User> findAllUsers();
//查询所有用户
List<User> findAllUsersResultMap();
//根据id查询
User findById(int id);
//模糊查询:根据用户名进行模糊查询
List<User> findByName(String username);
}
2 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="cn.itcast.dao.UserDao">
<!--保存用户
#{} : 占位符
-->
<insert id="save" parameterType="cn.itcast.domain.User">
insert into
user (username,birthday,sex,address)
values
(#{username},#{birthday},#{sex},#{address})
</insert>
<!--更新用户-->
<update id="update">
update user SET
username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
WHERE
id=#{id}
</update>
<!--根据id删除用户
parameterType: 传入的参数类型
自定义的java对象:对象的权限定类名
基本数据类型(包装类型和String):基本数据类型,不区分大小写
可以省略
占位符:#{}
自定义的java对象:对象中的属性
基本数据类型(包装类型和String):随便写
-->
<delete id="delete" parameterType="iNt">
delete from user where id=#{id}
</delete>
<!--
查询所有用户
resultType : 需要将查询数据封装的对象类型
语法:对象的权限定类名
条件:查询的字段和对象的属性保持一致
-->
<select id="findAllUsers" resultType="cn.itcast.domain.User">
select * from user
</select>
<!--
属性名和查询字段不一直:不能用resultType描述返回值
使用resultMap描述映射关系
resultMap :
id:唯一标志
type:经过resultMap转化后的对象类型
id标签:配置主键的映射关系
result标签:配置普通属性的映射关系
column:从字段抄
property:从实体类抄
-->
<resultMap id="userMap" type="cn.itcast.domain.User">
<!--主键-->
<id column="_id" property="id"></id>
<!--普通属性-->
<result column="_name" property="username"></result>
<result column="birthday" property="birthday"></result>
<result column="userSex" property="sex"></result>
<result column="abc" property="address"></result>
</resultMap>
<select id="findAllUsersResultMap" resultMap="userMap">
SELECT id _id,username _name,birthday, sex userSex, address abc FROM USER
</select>
<!--根据id查询-->
<select id="findById" parameterType="int" resultType="cn.itcast.domain.User">
select * from user where id=#{id}
</select>
<!--
模糊查询:根据用户名进行模糊查询
SELECT * FROM USER WHERE username LIKE '%王%'
#{} : 占位符
自定义的java对象:对象中的属性 #{对象属性}
基本数据类型(包装类型和String):#{随便写}
使用preparedStatment处理占位符,经过预编译,没有sql注入的风险
${} : 字符串拼接
自定义的java对象:对象中的属性 ${对象属性}
基本数据类型(包装类型和String):${value}
使用statment处理字符串拼接,不经过预编译,具有sql注入的风险
-->
<select id="findByName" parameterType="string" resultType="cn.itcast.domain.User">
select * from user where username like #{username}
</select>
</mapper>
namespace内填写: 接口的全限定名
标签内的 id属性内:填写方法名
标签内的 parameterType属性内:填写传入的参数类型
标签内的 resultType : 需要将查询数据封装的对象类型 内填写对象的权限定类名
sql语句内的 (?占位符) 使用#{对象的属性}来代替?
resultMap标签:
id:唯一标志 内容与select标签内的resultMap内的内容保持一致
type:经过resultMap转化后的对象类型
id标签:配置主键的映射关系
result标签:配置普通属性的映射关系
column:从字段抄
property:从实体类抄
模糊查询:根据用户名进行模糊查询
SELECT * FROM USER WHERE username LIKE '%王%'
#{} : 占位符
自定义的java对象:对象中的属性 #{对象属性}
基本数据类型(包装类型和String):#{随便写}
使用preparedStatment处理占位符,经过预编译,没有sql注入的风险
${} : 字符串拼接
自定义的java对象:对象中的属性 ${对象属性}
基本数据类型(包装类型和String):${value}
使用statment处理字符串拼接,不经过预编译,具有sql注入的风险
3 UserDaoTest
package cn.itcast.test;
import cn.itcast.dao.UserDao;
import cn.itcast.domain.User;
import cn.itcast.utils.BaseTestUtil;
import org.junit.Test;
import java.util.List;
public class UserDaoTest extends BaseTestUtil {
//测试保存
@Test
public void testSave() {
//1.创建dao接口的动态代理对象(实现类)
UserDao userDao = session.getMapper(UserDao.class);
//2.调用dao方法保存用户
User user = new User();
user.setUsername("lol");
user.setAddress("初中");
userDao.save(user);
}
//测试更新
@Test
public void testUpdate() {
//1.创建动态代理对象
UserDao userDao = session.getMapper(UserDao.class);
//2.调用dao完成更新用户
User user = new User();
user.setUsername("lol1");
user.setAddress("初中1");
user.setId(229);
userDao.update(user);
}
//测试删除
@Test
public void testDelete() {
//1.创建动态代理对象
UserDao userDao = session.getMapper(UserDao.class);
//2.调用dao完成删除用户
userDao.delete(229);
}
//测试查询全部
@Test
public void testFindAllUsers() {
//1.创建动态代理对象
UserDao userDao = session.getMapper(UserDao.class);
//2.调用dao完成删除用户
List<User> users = userDao.findAllUsers();
for (User user : users) {
System.out.println(user);
}
}
//测试查询全部
@Test
public void testFindAllUsersResultMap() {
//1.创建动态代理对象
UserDao userDao = session.getMapper(UserDao.class);
//2.调用dao完成删除用户
List<User> users = userDao.findAllUsersResultMap();
for (User user : users) {
System.out.println(user);
}
}
//测试根据id查询
@Test
public void testFindById() {
//1.创建动态代理对象
UserDao userDao = session.getMapper(UserDao.class);
//2.调用dao
User user = userDao.findById(228);
System.out.println(user);
}
//测试模糊查询
/**
* 方式一:(重点)
* 参数:查询条件在参数上进行的拼接
* SQL: select * from user where username like #{username}
* 方式二:(不用)
* 参数:只传递数据 : 王
* 模糊查询条件:sql映射文件中拼接
* SQL: select * from user where username like "%"#{username}"%"
* "%"#{username}"%":mysql语法中的字符串拼接
* 方式三:(不用)
* 参数:只传递数据 : 王
* 模糊查询条件:sql映射文件中拼接
* mysql的函数方法 concat() ,对方法中的字符串拼接
* sql语句: select * from user where username like concat('%',#{username},'%')
* 方式四:(不用)
* 参数:只传递数据 : 王
* 模糊查询条件:sql映射文件中拼接
* 使用${} 拼接
* select * from user where username like '%${value}%'
*/
@Test
public void testFindByName() {
//1.创建动态代理对象
UserDao userDao = session.getMapper(UserDao.class);
//2.调用dao
List<User> users = userDao.findByName("%王%");
for (User user : users) {
System.out.println(user);
}
}
}
2. Mybatis的多参数查询 获取主键 动态SQL (重点 各种标签) 多表关系(一对多 多对多)
1 UserDao接口
package cn.itcast.dao;
import cn.itcast.domain.QueryVo;
import cn.itcast.domain.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserDao {
/**
* 多个参数的查询:根据用户名和性别查询
* 方式一: 使用mybatis的默认参数别名(了解)
* 和传入的参数一一对应
* 第一个参数: arg0 或者 param1
* 第二个参数: arg1 或者 param2
*/
List<User> findByNameAndSex1(String username,String sex);
/**
* 方式二: 使用@Param注解配置到方法参数之前,对传入的参数自定义别名
* value:自定义的别名
*/
List<User> findByNameAndSex2(@Param("name") String username,@Param("userSex") String sex);
/**
* 方式三:将多个参数封装到对象中
*/
List<User> findByNameAndSex3(User user);
/**
* 保存用户
*/
void save(User user);
/**
* 多条件查询
*/
List<User> findByUser(User user);
/**
* 测试 choose , when otherwise
*/
List<User> findByUserChoose(User user);
/**
* 更新用户
*/
void update(User user);
/**
* 根据用户id的集合查询用户
*/
List<User> findByCollection(List<Integer> ids);
/**
* 根据用户id的数组查询用户
*/
List<User> findByArray(int [] ids);
/**
* 根据vo对象(封装了用户id的集合或者数组)查询用户
*/
List<User> findByVo(QueryVo vo);
}
2 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="cn.itcast.dao.UserDao">
<!--
多个参数的查询:根据用户名和性别查询
-->
<select id="findByNameAndSex1" resultType="cn.itcast.domain.User">
select * from user where sex=#{arg1} and username=#{arg0}
</select>
<select id="findByNameAndSex2" resultType="cn.itcast.domain.User">
select * from user where sex=#{userSex} and username=#{name}
</select>
<select id="findByNameAndSex3" resultType="cn.itcast.domain.User" parameterType="cn.itcast.domain.User">
select * from user where sex=#{sex} and username=#{username}
</select>
<!--
保存用户,获取保存之后的主键ID
方式一: 使用useGeneratedKeys结合keyProperty获取
useGeneratedKeys: 配置是否获取自动增长的id (false|true)
keyProperty: 主键id需要赋值到的对象属性
* 只能获取数据库中自动增长的id
<insert id="save" useGeneratedKeys="true" keyProperty="id" parameterType="cn.itcast.domain.User">
insert into user
(username,birthday,sex,address)
values
(#{username},#{birthday},#{sex},#{address})
</insert>
-->
<!--
保存用户,获取保存之后的主键ID
方式二: 先保存,再更新(last_insert_id())
selectKey : 获取保存之后的主键id
order : 当前sql语句的执行顺序(BEFORE|AFTER)
resultType : 配置返回值类型
keyProperty :主键id需要赋值到的对象属性
-->
<insert id="save" useGeneratedKeys="true" keyProperty="id" parameterType="cn.itcast.domain.User">
<selectKey order="AFTER" resultType="int" keyProperty="id">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user
(username,birthday,sex,address)
values
(#{username},#{birthday},#{sex},#{address})
</insert>
<!--
多条件查询
动态sql:if标签
String sql = "select * from user where 1=1"
if(username!=null && username!=""){
and username=?
}
if(sex!=null && sex!='') {
and sex=?
}
动态sql:where标签
用于SQL优化,根据判断体中的内容自动的添加where条件,
对前面多余的and进行优化(删除)
-->
<select id="findByUser" parameterType="cn.itcast.domain.User" resultType="cn.itcast.domain.User">
select * from user
<!--<where>-->
<trim prefix="where" prefixOverrides="and">
<if test="username!=null and username!=''">
and username=#{username}
</if>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
</trim>
<!-- </where>-->
</select>
<!--
动态sql: choose,when,otherwise
相当于java代码中的 if,else if ,else
-->
<select id="findByUserChoose" parameterType="cn.itcast.domain.User" resultType="cn.itcast.domain.User">
select * from user
<where>
<choose>
<when test="username!=null and username!=''">
and username=#{username}
</when>
<when test="sex!=null and sex!=''">
and sex=#{sex}
</when>
<otherwise>
and id=45
</otherwise>
</choose>
</where>
</select>
<!--
更新用户
动态sql: set
添加更新的set语句,优化更新语句中最后多余的","
动态sql:trim
替换where和set
prefix : 自动生成标签,在判断体之前
suffix : 自动生成标签,在判断体之后
prefixOverrides : 优化SQL语句中前面多余的sql片段(, and)
suffixOverrides : 优化SQL语句中后面多余的sql片段(, and)
-->
<update id="update" parameterType="cn.itcast.domain.User">
update user
<!-- <set>-->
<trim prefix="set" suffixOverrides=",">
<if test="username!=null and username!=''">
username=#{username},
</if>
<if test="birthday!=null">
birthday=#{birthday},
</if>
<if test="address!=null and address!=''">
address=#{address},
</if>
<if test="sex!=null and sex!=''">
sex=#{sex},
</if>
</trim>
<!-- </set>-->
where id=#{id}
</update>
<!--
根据用户id的集合查询用户
SQL: SELECT * FROM USER WHERE id IN (41,42,48)
String sql = "SELECT * FROM USER WHERE "
sql+= "id IN (";
for(Integer id : list) {
sql+= id;
sql+= ","
}
//处理多余的","(省略)
sql+=")"
动态sql : foreach标签(循环迭代)
collection : 描述参数类型
传入集合数据类型: collection
传入数组类型(int[],String[]): array
传入的java对象(包含数组|集合属性): 数组|集合属性的名称
open: 进入循环体之前执行的sql片段
close: 执行循环体之后执行的sql片段
item:对循环中每个元素设置别名
separator: 拼接多个字符串的分割符号
-->
<select id="findByCollection" resultType="cn.itcast.domain.User">
SELECT * FROM USER WHERE
<foreach collection="array" open="id IN (" close=")" item="id" separator=",">
#{id}
</foreach>
</select>
<!--
传入数组
collection : array
-->
<select id="findByArray" resultType="cn.itcast.domain.User">
SELECT * FROM USER WHERE id in
<foreach collection="collection" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</select>
<!--
传入java对象
collection : 对象中集合或者属性的属性名
-->
<select id="findByVo" resultType="cn.itcast.domain.User" parameterType="cn.itcast.domain.QueryVo">
SELECT * FROM USER WHERE id in
<foreach collection="ids" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</select>
</mapper>
**重要总结**
多参数查询: 推荐方式三:将多个参数封装到对象中
<select id="findByNameAndSex3" resultType="cn.itcast.domain.User" parameterType="cn.itcast.domain.User">
select * from user where sex=#{sex} and username=#{username}
</select>
获取主键:
方式一:
insert标签内的:
useGeneratedKeys: 配置是否获取自动增长的id (false|true) 相当于开关
keyProperty: 主键id需要赋值到的对象属性 赋值的对象属性
* 只能获取数据库中自动增长的id
<insert id="save" useGeneratedKeys="true" keyProperty="id" parameterType="cn.itcast.domain.User">
insert into user
(username,birthday,sex,address)
values
(#{username},#{birthday},#{sex},#{address})
</insert>
方式二: 先保存再更新
selectKey : 获取保存之后的主键id
order : 当前sql语句的执行顺序(BEFORE|AFTER)
resultType : 配置返回值类型
keyProperty :主键id需要赋值到的对象属性
<selectKey order="AFTER" resultType="int" keyProperty="id">
SELECT LAST_INSERT_ID()
</selectKey>
动态sql(重点)
在sql语句中完成判断,循环等java功能
1 if标签
2 where标签
用于SQL优化,根据判断体中的内容自动的添加where条件
对前面多余的and进行优化(删除)
3 choose when otherwise标签
相当于java代码中的 if,else if ,else
4 set标签:
作用更新用户
动态sql: set
添加更新的set语句,优化更新语句中最后多余的","
5 trim标签(了解)
trim标签主要作用:替换where和set标签 用于sql代码的优化
动态sql: set
添加更新的set语句,优化更新语句中最后多余的","
动态sql:trim
替换where和set
prefix : 自动生成标签,在判断体之前
suffix : 自动生成标签,在判断体之后
prefixOverrides : 优化SQL语句中前面多余的sql片段(, and)
suffixOverrides : 优化SQL语句中后面多余的sql片段(, and)
6 foreach标签
动态sql: foreach标签(循环迭代)
根据用户id的集合查询用户
SQL: SELECT * FROM USER WHERE id IN (41,42,48)
String sql = "SELECT * FROM USER WHERE "
sql+= "id IN (";
for(Integer id : list) {
sql+= id;
sql+= ","
}
//处理多余的","(省略)
sql+=")"
动态sql : foreach标签(循环迭代)
collection : 描述参数类型
传入集合数据类型: collection
传入数组类型(int[],String[]): array
传入的java对象(包含数组|集合属性): 数组|集合属性的名称
open: 进入循环体之前执行的sql片段
close: 执行循环体之后执行的sql片段
item:对循环中每个元素设置别名 id
separator: 拼接多个字符串的分割符号 ,
3 UserDaoTest
package cn.itcast.test;
import cn.itcast.dao.UserDao;
import cn.itcast.domain.QueryVo;
import cn.itcast.domain.User;
import cn.itcast.utils.BaseTestUtil;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class UserDaoTest extends BaseTestUtil {
@Test
public void testFindByNameAndSex() {
//1.创建动态代理对象(dao接口的实现类)
UserDao userDao = session.getMapper(UserDao.class);
//2.操作数据库
User user = new User();
user.setSex("男");
user.setUsername("老王");
List<User> list = userDao.findByNameAndSex3(user);
for (User user1 : list) {
System.out.println(user1);
}
}
//测试保存
@Test
public void testSave() {
//1.创建动态代理对象(dao接口的实现类)
UserDao userDao = session.getMapper(UserDao.class);
//2.操作数据库
User user = new User();
user.setUsername("王者荣耀");
user.setBirthday(new Date());
user.setSex("女");
user.setAddress("幼儿园");
userDao.save(user);
//获取保存之后的id
System.out.println("主键="+user.getId());
}
//测试多条件查询(if标签)
@Test
public void testFindByUser() {
User user = new User();
user.setUsername("王者荣耀");
user.setSex("女");
//1.创建动态代理对象(dao接口的实现类)
UserDao userDao = session.getMapper(UserDao.class);
//2.操作数据库
List<User> users = userDao.findByUser(user);
for (User user1 : users) {
System.out.println(user1);
}
}
//测试choose,when,otherwise
@Test
public void testFindByUserChoose() {
User user = new User();
//user.setUsername("王者荣耀");
//user.setSex("女");
//1.创建动态代理对象(dao接口的实现类)
UserDao userDao = session.getMapper(UserDao.class);
//2.操作数据库
List<User> users = userDao.findByUserChoose(user);
for (User user1 : users) {
System.out.println(user1);
}
}
//测试更新
@Test
public void testUpdate() {
User user = new User();
user.setUsername("LOL1");
user.setSex("男");
user.setId(243);
//1.创建动态代理对象(dao接口的实现类)
UserDao userDao = session.getMapper(UserDao.class);
//2.操作数据库
userDao.update(user);
}
//测试foreach标签,传递集合
@Test
public void testFindByCollection() {
List<Integer> ids = new ArrayList<>();
ids.add(41);
ids.add(42);
ids.add(48);
//1.创建动态代理对象(dao接口的实现类)
UserDao userDao = session.getMapper(UserDao.class);
//2.操作数据库
List<User> list = userDao.findByCollection(ids);
for (User user : list) {
System.out.println(user);
}
}
//测试foreach标签,传递数组
@Test
public void testFindByArray() {
int [] ids = new int[]{41,42,48};
//1.创建动态代理对象(dao接口的实现类)
UserDao userDao = session.getMapper(UserDao.class);
//2.操作数据库
List<User> list = userDao.findByArray(ids);
for (User user : list) {
System.out.println(user);
}
}
//测试foreach标签,传递对象
@Test
public void testFindByVo() {
List<Integer> ids = new ArrayList<>();
ids.add(41);
ids.add(42);
ids.add(48);
QueryVo vo = new QueryVo();
vo.setIds(ids);
//1.创建动态代理对象(dao接口的实现类)
UserDao userDao = session.getMapper(UserDao.class);
//2.操作数据库
List<User> list = userDao.findByVo(vo);
for (User user : list) {
System.out.println(user);
}
}
}