目录
基于代理 Dao 实现 CRUD 操作
使用要求:
1、持久层接口和持久层接口的映射配置必须在相同的包下
2、持久层映射配置中 mapper 标签的 namespace 属性取值必须是持久层接口的全限定类名
3、SQL 语句的配置标签<select>,<insert>,<delete>,<update>的 id 属性必须和持久层接口的
方法名相同。
代码
User实体类
package code.domain;
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
IUserDao.xml中配置sql语句
<?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">
<!--namespace指的是你的dao接口-->
<mapper namespace="code.dao.IUserDao">
<!--配置查询所有 其中id不能乱写必须是dao接口中的方法 resultType写的是实体类的全路径-->
<select id="findAll" resultType="code.domain.User">
select * from user
</select>
<insert id="saveUser" parameterType="code.domain.User">
insert into user(username,password)values (#{username},#{password})
</insert>
<update id="updataUser" parameterType="code.domain.User">
update user set password=#{password} where username=#{username};
</update>
<delete id="deleteUser" parameterType="string">
delete from user where username=#{value};
</delete>
<!--模糊查询用户-->
<select id="findByName" parameterType="string" resultType="code.domain.User">
select * from user where username like '%${value}%';
</select>
<select id="findTotal" resultType="int">
select count(*) from user ;
</select>
</mapper>
Test测试类执行sql语句
/**
*Mybatis初级测试
* */
public class MybatisTest {
/**
* 测试查询所有操作
* */
InputStream in;
SqlSessionFactory factory;
SqlSession sqlSession;
IUserDao userDao;
@Before
public void init() throws IOException {
//1.读取配置文件
in= Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
factory=new SqlSessionFactoryBuilder().build(in);
//3.使用工厂生产sqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
//在这里userdao是代理对象,而不需要像以前一样再去创建impl对象
userDao = sqlSession.getMapper(IUserDao.class);
}
@After
public void destroy() throws IOException {
//6.释放资源
sqlSession.close();
in.close();
}
/**
* 查询所有
* */
@Test
public void testfindAll(){
//5.使用代理对象增强方法,在不改变接口方法的基础上实现方法
List<User> users = userDao.findAll();
for (User user:users){
System.out.println(user);
}
}
/**
* 添加用户
* */
@Test
public void testsaveUser(){
User user=new User();
user.setUsername("王涵");
user.setPassword("wanghan");
userDao.saveUser(user);
sqlSession.commit();
}
/**
* 更新一条用户的记录*/
@Test
public void testupdateUser(){
User user=new User();
user.setUsername("林青霞");
user.setPassword("linqingxai");
userDao.updataUser(user);
sqlSession.commit();
}
/**
* 删除一条记录
* */
@Test
public void testdeleteUser(){
userDao.deleteUser("李彤");
sqlSession.commit();
}
/**
* 模糊查询
* */
@Test
public void testfindByNamer(){
List<User> users = userDao.findByName("霞");
// sqlSession.commit();
for (User user:users){
System.out.println(user);
}
}
/**
* 使用聚合函数
* */
@Test
public void testfindTotal(){
int total = userDao.findTotal();
System.out.println(total);
}
/**
* 参数的深入:使用POJO类作为参数
* */
@Test
public void testfindByVo(){
QueryVo vo=new QueryVo();
User user=new User();
user.setUsername("%王%");
vo.setUser(user);
List<User> users = userDao.findByVo(vo);
for (User u:users){
System.out.println(u);
}
}
/**
* 当User2中的成员变量名称与数据库中的不一致时,查询所有
* */
@Test
public void testfindAll2(){
//5.使用代理对象增强方法,在不改变接口方法的基础上实现方法
List<User2> users2 = userDao.findAll2();
for (User2 user2:users2){
System.out.println(user2);
}
}
}
Mybatis 的参数深入
parameterType注意事项
- 基 本类型和 String 我 们可 以直接 写类型 名称 ,也 可以 使用包 名 . 类名的 方式 ,例如 :java.lang.String。
- 实体类类型,目前我们只能使用全限定类名
- 传递 pojo 包装对象,参数深入
如:
1.编写 QueryVo
package code.domain;
import java.io.Serializable;
public class QueryVo implements Serializable {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
2.编写持久层接口
/**
* 根据 QueryVo 中的条件查询用户
* @param vo
* @return
*/
List<User> findByVo(QueryVo vo);
3.持久层接口的映射 文件
<select id="findByVo" resultType="code.domain.User" parameterType="code.domain.QueryVo">
select * from user where username like #{user.username};
</select>
4.测试包装类作为参数
/**
* 参数的深入:使用POJO类作为参数
* */
@Test
public void testfindByVo(){
QueryVo vo=new QueryVo();
User user=new User();
user.setUsername("%王%");
vo.setUser(user);
List<User> users = userDao.findByVo(vo);
for (User u:users){
System.out.println(u);
}
}
Mybatis 的输出结果封装
resultType注意事项:
当domain实体类与数据库中的字段值不一致时怎么办?
1.采用取别名方法
2.resultMap 设置映射结果类型
第一种方法:
起别名方法 运行起来比较快
使用别名查询
<!-- 配置查询所有操作 -->
<select id="findAll2" resultType="code.domain.User2">
select username as name ,password as psw from user;
</select>
思考:
如果我们的查询很多,都使用别名的话写起来岂不是很麻烦,有没有别的解决办法呢?
第二种方法
resultMap 采用配置的方式:配置查询结果的列名和类的属性名 映射对应关系
resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。
在 select 标签中使用 resultMap 属性指定引用即可。同时 resultMap 可以实现将查询结果映射为复杂类
型的 pojo,比如在查询结果映射对象中包括 pojo 和 list 实现一对一查询和一对多查询。
public class User2 {
private String name;
private String psw;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPsw() {
return psw;
}
public void setPsw(String psw) {
this.psw = psw;
}
@Override
public String toString() {
return "User2{" +
"name='" + name + '\'' +
", psw='" + psw + '\'' +
'}';
}
}
使用resultMap设置对应关系
<!-- 配置 查询结果的列名和实体类的属性名的对应关系-->
<resultMap id="UserMap" type="code.domain.User2">
<!-- 主键字段的对应-->
<!-- <id property="userId" column="uid"></id>-->
<!-- 非主键字段的对应-->
<result property="name" column="username"></result>
<result property="psw" column="password"></result>
</resultMap>
<select id="findAll2" resultMap="UserMap">
select * from user;
</select>