复杂映射&配置文件深入
一 Mybatis高级查询
1.1 ResutlMap属性
- 建立对象关系映射
* resultType
如果实体的属性名与表中字段名一致,将查询结果自动封装到实体类中
* ResutlMap
如果实体的属性名与表中字段名不一致,可以使用ResutlMap实现手动封装到实体类中
1) 编写UserMapper接口
package com.myProject.mapper;
import com.myProject.domain.User;
import java.util.List;
public interface UserMapper {
/**
* 根据id查询用户
*/
public User findUserById(int id);
/**
* 查询所有用户
* @return
*/
public List<User> findAllResultMap();
}
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="com.myProject.mapper.UserMapper">
<!--根据id查询用户-->
<select id="findUserById" parameterType="int" resultMap="userResultMap">
select * from user where id = #{id}
</select>
<!--id:标签的唯一标识
type: 封装后实体类型
-->
<resultMap id="userResultMap" type="com.myProject.domain.User">
<!--手动配置映射关系-->
<!--id: 用来配置主键-->
<id property="id" column="id"></id>
<!--result: 表中普通字段的封装-->
<result property="usernameabc" column="username"></result>
<result property="birthdayabc" column="birthday"></result>
<result property="sexabc" column="sex"></result>
<result property="addressabc" column="address"></result>
</resultMap>
<!--查询所有用户-->
<!--resultMap:手动配置实体属性与表中字段的映射关系,完成手动封装-->
<select id="findAllResultMap" resultMap="userResultMap">
select * from user
</select>
</mapper>
3)代码测试
package com.myProject.test;
import com.myProject.domain.User;
import com.myProject.mapper.UserMapper;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MybatisTest {
/**
* mybatis的Dao层mapper代理方法测试
*/
@Test
public void test1() throws IOException {
// 加载核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获得SqlSessionFactory工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
// 获得SqlSession会话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.findUserById(1);
System.out.println(user);
// 释放资源
sqlSession.close();
}
@Test
public void test2() throws IOException {
// 加载核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获得SqlSessionFactory工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
// 获得SqlSession会话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findAllResultMap();
users.forEach(System.out::println);
// 释放资源
sqlSession.close();
}
}
1.2 多条件查询(三种)
需求
- 根据id和username查询user表
1)方式一
使用 #{arg0}-#{argn}
或者 #{param1}-#{paramn}
获取参数
- UserMapper接口
package com.myProject.mapper;
import com.myProject.domain.User;
import java.util.List;
public interface UserMapper {
/**
* 多条件查询:方式一
*/
public List<User> findByIdAndUsername1(int id, String username);
}
- 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.myProject.mapper.UserMapper">
<!--id:标签的唯一标识
type: 封装后实体类型
-->
<resultMap id="userResultMap" type="com.myProject.domain.User">
<!--手动配置映射关系-->
<!--id: 用来配置主键-->
<id property="id" column="id"></id>
<!--result: 表中普通字段的封装-->
<result property="usernameabc" column="username"></result>
<result property="birthdayabc" column="birthday"></result>
<result property="sexabc" column="sex"></result>
<result property="addressabc" column="address"></result>
</resultMap>
<!--多条件查询:方式一-->
<select id="findByIdAndUsername1" resultMap="userResultMap">
<!--使用arg作为参数传递,是从0开始-->
<!--select * from user where id = #{arg0} and username = #{arg1}-->
<!--使用param作为参数传递,是从1开始-->
select * from user where id = #{param1} and username = #{param2}
</select>
</mapper>
- 测试
/**
* 多条件查询:方式一
*/
@Test
public void test() throws IOException {
// 加载核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获得SqlSessionFactory工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
// 获得SqlSession会话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findByIdAndUsername1(1, "子慕");
users.forEach(System.out::println);
// 释放资源
sqlSession.close();
}
2)方式二
使用注解,引入 @Param()
注解获取参数
- UserMapper接口
package com.myProject.mapper;
import com.myProject.domain.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserMapper {
/**
* 多条件查询: 方式二
* @Param传入的参数要见名知意,所以要与findByIdAndUsername2()形式参数保持一致
*/
public List<User> findByIdAndUsername2(@Param("id") int id, @Param("username") String username);
}
- 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.myProject.mapper.UserMapper">
<!--id:标签的唯一标识
type: 封装后实体类型
-->
<resultMap id="userResultMap" type="com.myProject.domain.User">
<!--手动配置映射关系-->
<!--id: 用来配置主键-->
<id property="id" column="id"></id>
<!--result: 表中普通字段的封装-->
<result property="usernameabc" column="username"></result>
<result property="birthdayabc" column="birthday"></result>
<result property="sexabc" column="sex"></result>
<result property="addressabc" column="address"></result>
</resultMap>
<!--多条件查询:方式二-->
<select id="findByIdAndUsername2" resultMap="userResultMap">
select * from user where id = #{id} and username = #{username}
</select>
</mapper>
- 测试
/**
* 多条件查询:方式二
*/
@Test
public void test() throws IOException {
// 加载核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获得SqlSessionFactory工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
// 获得SqlSession会话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findByIdAndUsername2(1, "子慕");
users.forEach(System.out::println);
// 释放资源
sqlSession.close();
}
3)方式三(推荐)
使用pojo(实体)对象传递参数
- UserMapper接口
package com.myProject.mapper;
import com.myProject.domain.User;
import java.util.List;
public interface UserMapper {
/**
* 多条件查询:方式三
*/
public List<User> findByIdAndUsername3(User user);
}
- 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.myProject.mapper.UserMapper">
<!--id:标签的唯一标识
type: 封装后实体类型
-->
<resultMap id="userResultMap" type="com.myProject.domain.User">
<!--手动配置映射关系-->
<!--id: 用来配置主键-->
<id property="id" column="id"></id>
<!--result: 表中普通字段的封装-->
<result property="usernameabc" column="username"></result>
<result property="birthdayabc" column="birthday"></result>
<result property="sexabc" column="sex"></result>
<result property="addressabc" column="address"></result>
</resultMap>
<!--多条件查询:方式三-->
<select id="findByIdAndUsername3" resultMap="userResultMap" parameterType="com.myProject.domain.User">
select * from user where id = #{id} and username = #{usernameabc}
</select>
</mapper>
- 测试
/**
* 多条件查询:方式三
*/
@Test
public void test() throws IOException {
// 加载核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获得SqlSessionFactory工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
// 获得SqlSession会话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setId(1);
user.setUsernameabc("子慕");
List<User> users = mapper.findByIdAndUsername3(user);
users.forEach(System.out::println);
// 释放资源
sqlSession.close();
}
1.3 模糊查询
需求
1)方式一
- UserMapper接口
package com.myProject.mapper;
import com.myProject.domain.User;
import java.util.List;
public interface UserMapper {
/**
* 模糊查询:方式一
*/
public List<User> findByUsername(String username);
}
- 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.myProject.mapper.UserMapper">
<!--id:标签的唯一标识
type: 封装后实体类型
-->
<resultMap id="userResultMap" type="com.myProject.domain.User">
<!--手动配置映射关系-->
<!--id: 用来配置主键-->
<id property="id" column="id"></id>
<!--result: 表中普通字段的封装-->
<result property="usernameabc" column="username"></result>
<result property="birthdayabc" column="birthday"></result>
<result property="sexabc" column="sex"></result>
<result property="addressabc" column="address"></result>
</resultMap>
<!--模糊查询:方式一-->
<select id="findByUsername" resultMap="userResultMap" parameterType="string">
<!--#{}:在mybatis中是占位符,引用参数值得时候会自动添加单引号
#{}:如果只有一个参数时,参数可自定义,但要见名知意
-->
select * from user where username like #{username}
</select>
</mapper>
- 测试
package com.myProject.test;
import com.myProject.domain.User;
import com.myProject.mapper.UserMapper;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MybatisTest {
/**
* 模糊查询:方式一
*/
@Test
public void test() throws IOException {
// 加载核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获得SqlSessionFactory工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
// 获得SqlSession会话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findByUsername("自动提交%");
users.forEach(System.out::println);
// 释放资源
sqlSession.close();
}
}
2)方式二
- UserMapper接口
package com.myProject.mapper;
import com.myProject.domain.User;
import java.util.List;
public interface UserMapper {
/**
* 模糊查询:方式二
*/
public List<User> findByUsername2(String username);
}
- 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.myProject.mapper.UserMapper">
<!--id:标签的唯一标识
type: 封装后实体类型
-->
<resultMap id="userResultMap" type="com.myProject.domain.User">
<!--手动配置映射关系-->
<!--id: 用来配置主键-->
<id property="id" column="id"></id>
<!--result: 表中普通字段的封装-->
<result property="usernameabc" column="username"></result>
<result property="birthdayabc" column="birthday"></result>
<result property="sexabc" column="sex"></result>
<result property="addressabc" column="address"></result>
</resultMap>
<!--模糊查询:方式二-->
<select id="findByUsername2" resultMap="userResultMap" parameterType="string">
<!--parameterType是基本数据类型或者String的时候,${}里面的值只能写value
${}:sql语句原样拼接,不会自动添加单引号
-->
select * from user where username like '${value}'
</select>
</mapper>
- 测试
package com.myProject.test;
import com.myProject.domain.User;
import com.myProject.mapper.UserMapper;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MybatisTest {
/**
* 模糊查询:方式二
*/
@Test
public void test() throws IOException {
// 加载核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获得SqlSessionFactory工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
// 获得SqlSession会话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findByUsername2("自动提交%");
users.forEach(System.out::println);
// 释放资源
sqlSession.close();
}
}
3) ${}
与 #{}
区别
#{}
:表示一个占位符号- 通过
#{}
可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}
可以有效防止sql注入。 #{}
可以接收简单类型值或pojo属性值。- 如果parameterType传输单个简单类型值,
#{}
括号中名称随便写。
- 通过
${}
:表示拼接sql串- 通过
${}
可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换,会出现sql注入问题。 ${}
可以接收简单类型值或pojo属性值。- 如果parameterType传输单个简单类型值,
${}
括号中只能是value。
- 通过
二 Mybatis映射文件深入
2.1 返回主键
应用场景
- 我们很多时候有这种需求,向数据库插入一条记录后,希望能立即拿到这条记录在数据库中的主键值。
2.1.1 useGeneratedKeys
- UserMapper接口
package com.myProject.mapper;
import com.myProject.domain.User;
public interface UserMapper {
/**
* 添加用户同时获取主键:方式一
*/
public void saveUser(User user);
}
- 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.myProject.mapper.UserMapper">
<!--添加用户同时获取主键:方式一-->
<!--useGeneratedKeys: 声明返回主键
keyProperty:把返回主键的值,封装到实体中的那个属性上
-->
<insert id="saveUser" parameterType="user" useGeneratedKeys="true" keyProperty="id">
insert into user(username, birthday, sex, address) values(#{username}, #{birthday}, #{sex}, #{address})
</insert>
</mapper>
- 测试
package com.myProject.test;
import com.myProject.domain.User;
import com.myProject.mapper.UserMapper;
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 java.io.IOException;
import java.io.InputStream;
import java.util.Date;
public class MybatisTest {
/**
* 添加用户同时返回主键:方式一
*/
@Test
public void test() throws IOException {
// 加载核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获得SqlSessionFactory工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
// 获得SqlSession会话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
UserMapper mapper = sqlSession