Java Web学习day19------Mybatis(注解、注解实现多表开发、构建SQL)

本文详细介绍了如何在MyBatis中使用注解开发CRUD操作,涵盖一对一、一对多、多对多的关系映射,并展示了如何构建SQL语句和动态SQL。此外,还提供了项目改进案例,包括环境搭建、配置调整和接口代理的实现。
摘要由CSDN通过智能技术生成

一. 注解开发实现CRUD【重要】

1. Mapper接口中使用注解

public interface StudentMapper {
    //查询全部
    @Select("SELECT * FROM student")
    public abstract List<Student> selectAll();

    //新增操作
    @Insert("INSERT INTO student VALUES (#{id},#{name},#{age})")
    public abstract Integer insert(Student stu);

    //修改操作
    @Update("UPDATE student SET name=#{name},age=#{age} WHERE id=#{id}")
    public abstract Integer update(Student stu);

    //删除操作
    @Delete("DELETE FROM student WHERE id=#{id}")
    public abstract Integer delete(Integer id);
}

2. 核心配置文件引入Mapper

  文件结构
在这里插入图片描述

<!--核心配置文件中配置-->
<!--加载映射文件-->
<mappers>
  <!--引入mapper接口的位置-->
  <!--使用mapper配置文件配置,class里面使用Mapper类的全类名-->
  <!--<mapper class="com.itheima.mapper.StudentMapper"/>-->
  <!--引入整个mapper包(扫包)-->
  <package name="com.itheima.mapper"/>
</mappers>

3. 测试类

public class Test01 {
    @Test
    public void selectAll() throws Exception{
        //1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
        //2.获取SqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        //3.通过工厂对象获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        //4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        //5.调用实现类对象中的方法,接收结果
        List<Student> list = mapper.selectAll();
        //6.处理结果
        for (Student student : list) {
            System.out.println(student);
        }
        //7.释放资源
        sqlSession.close();
        is.close();
    }

    @Test
    public void insert() throws Exception{
        //1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
        //2.获取SqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        //3.通过工厂对象获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        //4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        //5.调用实现类对象中的方法,接收结果
        Student stu = new Student(4,"赵六",26);
        Integer result = mapper.insert(stu);
        //6.处理结果
        System.out.println(result);
        //7.释放资源
        sqlSession.close();
        is.close();
    }

    @Test
    public void update() throws Exception{
        //1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
        //2.获取SqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        //3.通过工厂对象获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        //4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        //5.调用实现类对象中的方法,接收结果
        Student stu = new Student(4,"赵六",36);
        Integer result = mapper.update(stu);
        //6.处理结果
        System.out.println(result);
        //7.释放资源
        sqlSession.close();
        is.close();
    }

    @Test
    public void delete() throws Exception{
        //1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
        //2.获取SqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        //3.通过工厂对象获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        //4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        //5.调用实现类对象中的方法,接收结果
        Integer result = mapper.delete(4);
        //6.处理结果
        System.out.println(result);
        //7.释放资源
        sqlSession.close();
        is.close();
    }
}

4. 注意事项

(1)在使用注解的时候,如果核心配置文件中进行了扫包,那就可以不需要mapper.xml文件
(2)如果核心配置文件中配置了扫包的方式,在不使用注解,而使用mapper.xml的时候,xml文件和mapper文件放在同一个目录下,并且命名要相同
(3)如果配置扫包,注解方式和mapper.xml方式不能同时存在在mapper包内

二. 注解实现多表开发【重要】

  实现复杂关系映射之前我们可以在映射文件中通过配置<resultMap>来实现,使用注解开发后,我们可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置
在这里插入图片描述
在这里插入图片描述

1. 一对一

1.1 CardMapper接口中查询全部

public interface CardMapper {
    //查询全部
    @Select("SELECT * FROM card")
    //指定一对一封装的结果
    /*
        property:被包含对象的变量名
        javaType:被包含对象的实际数据类型
        column:根据查询出的card表中的pid字段来查询person表
        one=@One()一对一固定写法
        select属性:指定调用哪个接口中的哪个方法(一定要使用接口的全类名)
     */
    @Results({
            @Result(column = "id",property = "id"),
            @Result(column = "number",property = "number"),
            @Result(
            	property = "p",         //被包含对象的变量名
                javaType = Person.class,//被包含对象的实际数据类型
                column = "pid",         //根据查询出的card表中的pid字段来查询person表
                /*
                	one、@One 一对一固定写法
                    select属性:指定调用哪个接口中的哪个方法
               	*/
                one = @One(select = "com.itheima.one_to_one.PersonMapper.selectById")
            )
    })
    public abstract List<Card> selectAll();
}

1.2 PersonMaper接口中根据id查询

public interface PersonMapper {
  @Select("select * from person where id=#{id}")
  Person selectById(Integer id);
}

1.3 测试方法

/*
  测试一对一关系:查询所有card的信息,包括每个card对应的person信息
*/
@Test
public void selectAll() throws Exception{
	//1.加载核心配置文件
	InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
	//2.获取SqlSession工厂对象
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
	//3.通过工厂对象获取SqlSession对象
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	//4.获取CardMapper接口的实现类对象
	CardMapper mapper = sqlSession.getMapper(CardMapper.class);
	//5.调用实现类对象中的方法,接收结果
	List<Card> list = mapper.selectAll();
	//6.处理结果
	for (Card card : list) {
		System.out.println(card);
	}
	//7.释放资源
	sqlSession.close();
	is.close();
}

2. 一对多

2.1 ClassesMapper接口中查询全部

public interface ClassesMapper {
    //查询全部
    @Select("SELECT * FROM classes")
    //指定一对多封装的结果
    /*
        property: 被包含对象的变量名
        javaType: 被包含对象的实际数据类型
        column: 根据查询出的classes表的id字段来查询student表
        many=@Many: 一对多查询的固定写法
        select属性:指定调用哪个接口中的哪个查询方法
     */
    @Results({
        @Result(column = "id",property = "id"),
        @Result(column = "name",property = "name"),
        @Result(
            property = "students", //被包含对象的变量名
            javaType = List.class, //被包含对象的实际数据类型
            column = "id",         //根据查询出的classes表的id字段来查询student表
            /*
             many、@Many 一对多查询的固定写法
             select属性:指定调用哪个接口中的哪个查询方法
            */
            many = @Many(select = "com.itheima.one_to_many.StudentMapper.selectByCid")
       	)
    })
    public abstract List<Classes> selectAll();
}

2.2 StudentMaper接口中根据id查询

public interface StudentMapper {
  @Select("select * from student where cid=#{cid}")
  List<Student> selectByCid(int cid);
}

2.3 测试方法

/*
  测试一对多关系:查询所有班级以及该班级的所有学生信息
*/
@Test
public void selectAll() throws Exception{
	//1.加载核心配置文件
	InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
	//2.获取SqlSession工厂对象
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
	//3.通过工厂对象获取SqlSession对象
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	//4.获取ClassesMapper接口的实现类对象
	ClassesMapper mapper = sqlSession.getMapper(ClassesMapper.class);
	//5.调用实现类对象中的方法,接收结果
	List<Classes> list = mapper.selectAll();
	//6.处理结果
	for (Classes cls : list) {
		System.out.println(cls.getId() + "," + cls.getName());
		List<Student> students = cls.getStudents();
		for (Student student : students) {
			System.out.println("\t" + student);
		}
	}
	//7.释放资源
	sqlSession.close();
	is.close();
}

3. 多对多

3.1 StudentMapper接口中查询全部

public interface StudentMapper {
    //查询全部
    @Select("SELECT DISTINCT s.id,s.name,s.age FROM student s,stu_cr sc WHERE sc.sid=s.id")
    //指定多对多封装的结果
    /*
        property: 被包含对象的变量名
        javaType: 被包含对象的实际数据类型
        column: 根据查询出student表的id来作为关联条件,去查询中间表和课程表
        many=@Many 一对多查询的固定写法
        select属性:指定调用哪个接口中的哪个查询方法
     */
    @Results({
    	@Result(column = "id",property = "id"),
        @Result(column = "name",property = "name"),
        @Result(column = "age",property = "age"),
        @Result(
            property = "courses", //被包含对象的变量名
            javaType = List.class,//被包含对象的实际数据类型
            column = "id",     //根据查询出student表的id来作为关联条件去查询中间表和课程表
            /*
            many=@Many 一对多查询的固定写法
            select属性:指定调用哪个接口中的哪个查询方法
            */
            many = @Many(select = "com.itheima.many_to_many.CourseMapper.selectBySid")
      	)
    })
    public abstract List<Student> selectAll();
}

3.2 CourseMaper接口中根据id查询

public interface CourseMapper {
  @Select("select c.* from stu_cr sc,course c where sc.cid=c.id and sc.sid=#{sid}")
  public List<Course> selectBySid(Integer sid);
}

3.3 测试方法

/*
	测试多对多关系:查询所有学生及其选课信息
*/
@Test
public void selectAll() throws Exception{
	//1.加载核心配置文件
	InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
	//2.获取SqlSession工厂对象
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
	//3.通过工厂对象获取SqlSession对象
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	//4.获取StudentMapper接口的实现类对象
	StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
	//5.调用实现类对象中的方法,接收结果
	List<Student> list = mapper.selectAll();
	//6.处理结果
	for (Student student : list) {
		System.out.println(student.getId() + "," + student.getName() + "," + student.getAge());
		List<Course> courses = student.getCourses();
		for (Course cours : courses) {
			System.out.println("\t" + cours);
		}
	}
	//7.释放资源
	sqlSession.close();
	is.close();
}

三. 构建SQL【了解】

1. 提供类和方法返回Sql语句

public class ReturnSql {
    //定义方法,返回查询的sql语句
    public String getSelectAll() {
        return new SQL() {
            {
                SELECT("*");
                FROM("student");
            }
        }.toString();
    }
    
    //定义方法,返回新增的sql语句
    public String getInsert(Student stu) {
        return new SQL() {
            {
                INSERT_INTO("student");
                INTO_VALUES("#{id},#{name},#{age}");
            }
        }.toString();
    }

    //定义方法,返回修改的sql语句
    public String getUpdate(Student stu) {
        return new SQL() {
            {
                UPDATE("student");
                SET("name=#{name}","age=#{age}");
                WHERE("id=#{id}");
            }
        }.toString();
    }

    //定义方法,返回删除的sql语句
    public String getDelete(Integer id) {
        return new SQL() {
            {
                DELETE_FROM("student");
                WHERE("id=#{id}");
            }
        }.toString();
    }
}

2. 在Mapper接口方法上替换

//利用@XxxxProvider来使用构建的sql
public interface StudentMapper {
    //查询全部
    //@Select("SELECT * FROM student")
    @SelectProvider(type = ReturnSql.class , method = "getSelectAll")
    public abstract List<Student> selectAll();

    //新增功能
    //@Insert("INSERT INTO student VALUES (#{id},#{name},#{age})")
    @InsertProvider(type = ReturnSql.class , method = "getInsert")
    public abstract Integer insert(Student stu);

    //修改功能
    //@Update("UPDATE student SET name=#{name},age=#{age} WHERE id=#{id}")
    @UpdateProvider(type = ReturnSql.class , method = "getUpdate")
    public abstract Integer update(Student stu);

    //删除功能
    //@Delete("DELETE FROM student WHERE id=#{id}")
    @DeleteProvider(type = ReturnSql.class , method = "getDelete")
    public abstract Integer delete(Integer id);
}

3. 测试类测试

@Test
public void selectAll() throws Exception{
	//1.加载核心配置文件
	InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
	//2.获取SqlSession工厂对象
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
	//3.通过工厂对象获取SqlSession对象
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	//4.获取StudentMapper接口的实现类对象
	StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
	//5.调用实现类对象中的方法,接收结果
	List<Student> list = mapper.selectAll();
	//6.处理结果
	for (Student student : list) {
		System.out.println(student);
	}
	//7.释放资源
	sqlSession.close();
	is.close();
}

@Test
public void insert() throws Exception{
	//1.加载核心配置文件
	InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
	//2.获取SqlSession工厂对象
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
	//3.通过工厂对象获取SqlSession对象
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	//4.获取StudentMapper接口的实现类对象
	StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
	//5.调用实现类对象中的方法,接收结果
	Student stu = new Student(4,"赵六",26);
	Integer result = mapper.insert(stu);
	//6.处理结果
	System.out.println(result);
	//7.释放资源
	sqlSession.close();
	is.close();
}

@Test
public void update() throws Exception{
	//1.加载核心配置文件
	InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
	//2.获取SqlSession工厂对象
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
	//3.通过工厂对象获取SqlSession对象
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	//4.获取StudentMapper接口的实现类对象
	StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
	//5.调用实现类对象中的方法,接收结果
	Student stu = new Student(4,"赵六",36);
	Integer result = mapper.update(stu);
	//6.处理结果
	System.out.println(result);
	//7.释放资源
	sqlSession.close();
	is.close();
}

@Test
public void delete() throws Exception{
	//1.加载核心配置文件
	InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
	//2.获取SqlSession工厂对象
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
	//3.通过工厂对象获取SqlSession对象
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	//4.获取StudentMapper接口的实现类对象
	StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
	//5.调用实现类对象中的方法,接收结果
	Integer result = mapper.delete(4);
	//6.处理结果
	System.out.println(result);
	//7.释放资源
	sqlSession.close();
	is.close();
}

4. 构建动态sql

public class ReturnSql {
  public String getSelectCondition(Student stu){
        //select * from student where id=#{id} and name=#{name} and age=#{age}
        //创建初始化语句
        SQL sql = new SQL().SELECT("*").FROM("student");
        //判断
        if(stu!=null && stu.getId()!=null){
            sql.WHERE("id=#{id}");
        }
        if(stu!=null && stu.getName()!=null){
            sql.WHERE("name=#{name}"); //where方法会自动添加上and关键字
        }
        if(stu!=null && stu.getAge()!=null){
            sql.WHERE("age=#{age}"); //where方法会自动添加上and关键字
        }
        return sql.toString();
    }

  /*public String getSelectCondition(Student stu){
    //select * from student where id=#{id} and name=#{name} and age=#{age}
    //创建初始化语句
    StringBuilder sb=new StringBuilder("select * from student where 1=1");
    //判断
    if(stu!=null && stu.getId()!=null){
      sb.append(" and id=#{id}");
    }
    if(stu!=null && stu.getName()!=null){
      sb.append(" and name=#{name}");
    }
    if(stu!=null && stu.getAge()!=null){
      sb.append(" and age=#{age}");
    }
    return sb.toString();
  }*/
}

四. 案例改进

1. 项目环境搭建

(1)执行给定的sql,创建项目需要的数据库和表。
(2)创建动态web项目,项目名为mybatis_sms。
(3)将资料中mybatis_sms中的src目录和web目录中的所有内容复制到自己的mybatis_sms中
(4)修改config.properties中连接数据库的参数

2. mybatis环境搭建

(1)导入Mybatis的jar包和log4j的jar包
(2)导入核心配置问题和log4j配置文件和MyBatisUtils工具类
(3)修改核心配置文件中的数据库配置文件名称,标签中的路径也需要修改
(4)在StudentDao的方法上加上注解查询的sql语句
(5)在StudentServiceImpl中重写findAll()方法,使用接口代理的方式实现

3. 删除StudentDaoImpl,在StudentDao接口中使用注解配置CRUD

/*
    Dao层接口
 */
public interface StudentDao {
  //查询所有学生信息
  @Select("select * from student")
  public abstract ArrayList<Student> findAll();

  //条件查询,根据id获取学生信息
  @Select("select * from student where sid=#{id}")
  public abstract Student findById(Integer id);

  //新增学生信息
  @Insert("insert into student values (#{sid},#{name},#{age},#{birthday})")
  public abstract int insert(Student stu);

  //修改学生信息
  @Update("update student set name=#{name},age=#{age},birthday=#{birthday} where sid=#{sid}")
  public abstract int update(Student stu);

  //删除学生信息
  @Delete("delete from student where sid=#{sid}")
  public abstract int delete(Integer id);
}

4. 在utils包下导入编写好的MybatisUtils工具类

public class MyBatisUtils {
    //私有构造方法
    private MyBatisUtils(){}
    //声明工厂对象
    private static SqlSessionFactory sqlSessionFactory;
    //提供静态代码块,读取核心配置文件,并给工厂对象赋值
    static {
        try {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("MyBatisConfig.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //提供静态方法,获取SqlSession对象
    public  static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession(true);
    }
}

5. 在StudentServiceImpl中使用mybatis接口代理方式实现dao

public class StudentServiceImpl implements StudentService {
    @Override
    public List<Student> findAll() {
        //获SQLSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        //获取StudentDao接口的实现类对象
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        //调用实现类对象响应的功能
        ArrayList<Student> list = mapper.findAll();
        //释放资源
        sqlSession.close();
        //返回结果
        return list;
    }
    @Override
    public Student findById(Integer sid) {
        //获SQLSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        //获取StudentDao接口的实现类对象
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        //调用实现类对象响应的功能
        Student stu = mapper.findById(sid);
        //释放资源
        sqlSession.close();
        //返回结果
        return stu;
    }
    @Override
    public void save(Student student) {
        //获SQLSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        //获取StudentDao接口的实现类对象
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        //调用实现类对象响应的功能
        mapper.insert(student);
        //释放资源
        sqlSession.close();
    }
    @Override
    public void update(Student student) {
        //获SQLSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        //获取StudentDao接口的实现类对象
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        //调用实现类对象响应的功能
        mapper.update(student);
        //释放资源
        sqlSession.close();
    }
    @Override
    public void delete(Integer sid) {
        //获SQLSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        //获取StudentDao接口的实现类对象
        StudentDao mapper = sqlSession.getMapper(StudentDao.class);
        //调用实现类对象响应的功能
        mapper.delete(sid);
        //释放资源
        sqlSession.close();
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值