MyBatis高级

158 阅读5分钟

MyBatis注解开发

图片.png

注解实现查询操作
1.创建接口和查询方法
2.在核心配置文件中配置映射关系
3.编写测试类

学生表:

图片.png

核心配置文件中 指定映射关系(因为注解后就没有映射文件了)

图片.png

接口StudentMapper:

查询

图片.png

测试类:

图片.png

图片.png

新增操作

图片.png

测试类中 图片.png

返回主键自增

图片.png

图片.png

测试类:

图片.png

修改操作

图片.png

图片.png

删除操作

图片.png

图片.png

注解实现多表操作

注解之 一对一

CardMapper映射接口

public interface CardMapper{
    //1.查询全部,但是这个只对card表进行查询
    @Select("SELECT * FROM card")
    //为了能够搞到另一张表,就要用另个注解,得到结果映射
    @Results({
    //前面是表的数据,后面是card实体类的id
        @Result(column="id",property="id"),
        @Result(column="number",property="number"),
        @Result(//将查询出来card表的pid作为person表的查询条件
            property="p",//配包含对象的变量名
            javaType=Person.class//被包含对象的实际类型
            column="pid",//根据查询出的card表中的pid字段来查询person表
        
            //one,@One:就是一对一的固定写法
            //select属性:指定调用哪个接口中的哪个方法
            one = @One(select="PersonMapper.selectById的全路径")
        )
    })
    public abstract List<Card> selectAll();
}

PersonMapper映像接口

public interface PersonMapper{
    //根据id查询,根据上方查询出来的pid作为这里的id
    //将查询出来的person数据封装到person对象中
    @Select("SELECT * FROM person WHERE id=#{id}")
    public abstract Person selectById(Integer id);
}

Card实体类:

private Integer id;
private String number;
private Person p
经过上方的所有操作后,Card实体类中的这三个属性才会全部有值

图片.png

Test01测试类

图片.png

运行结果

demo08.gif

注解之一对多

每次一来第一件事:配置映射关系

图片.png

Student实例类

private Integer id;
private String name;
private Integer age;

Classes实例类

private Integer id;
private String name;
private List<Student> students; //一个班级有多个学生 一对多

ClassesMapper映射接口

public interface ClassesMapper{
    //查询全部,对查询出来的结果进行封装
    @Select("SELECT * FROM classes")
    @Results({
        @Result(column="id",property="id"),
        @Result(column="name",property="name"),
        //搞定<Student>,但是他又是另一张表的,所以用如下形式
        @Result(
        //被包含对象的变量名
            property = "students",
        //被包含对象的实际数据类型    
            javaType = List.class,
        //根据查询出的classes表中的id字段来查询student表
            colum="id",
        //这个id传到下面的StudentMapper中的cid中
        
        //一对多操作select:指定调用哪个接口中的哪个查询方法(全路径)
            many=@Many(select="...StudentMapper.selectByCid")
        ),
    })
    public abstract List<Classes> selectAll();
}

StudentMapper映射接口

public interface StudentMapper{

//根据cid查询student表,查询出来会有多个学生,所以保存在集合里
    @Select("SELECT * FROM student WHERE cid=#{cid}")
    public abstract List<Student> selectByCid(Integer cid);
}

Test01测试类

图片.png

运行结果:

图片.png

总结:
1.先在ClassesMapper中查询所有的classes中的数据
2.然后对里面的数据表字段数据进行封装到实体类中
3.实体类中有一个特殊的:被包含的集合对象,所以需要指定被包含对象的名字和实际数据类型
    并且指定被包含对象依据classes表中哪一个字段来查询我student表的
4.调用StudentMapper中的selectByCid,查询学生表的数据

图片.png

注解之 多对多

Student实例类

图片.png

StudentMapper映射接口

图片.png

CourseMapper映射接口

图片.png

Test01测试类

图片.png

小结:

图片.png

创建SQL语句

我们之前通过注解开发,相关SQL语句都是自己直接拼写的。一些关键字写起来比较麻烦、而且容易出错。

这些方法,替换了之前的Sql关键字,里面的参数就是Sql关键字里的列名。

图片.png

演示SqlTest

public class SqlTest{
    public static void main(String[] args){
        String sql = getSql();
        System.out.println(sql);
    }
    
    public static String getSql(){
        String sql = new SQL(){
            {
                //替代SELECT * FROM student
                SELECT("*"); //要查多少列
                FROM("studnet")//来自那张表
            }
        }.toString();
        
        return sql;
    }
}

查询操作

定义功能类 并提供获取 查询的SQL语句的方法。

@SelectProvider:生成查询用的SQL语句注释。
        type属性:生成SQL语句功能类对象
        method属性:指定调用方法

功能类:ReturnSql

public class ReturnSql{
    //定义方法,返回查询的sql语句
    public String getSelectAll(){
        return new SQL(){
            {
                SELECT("*");
                FROM("student");
            }
        }.toString();
    }
}

新增功能

@InsertProvider:生成新增用的SQL语句注解

public class ReturnSql{
    //定义方法,返回查询的sql语句
    public String getInsert(Student stu){
        return new SQL(){
            {
                INSERT_INTO("student"); 表名
                INTO_VALUES("#{id},#{name},#{age}"); 添加数据
                
            }
        }.toString();
    }
}

修改操作

@UpdateProvider:生成修改使用的SQL语句注解

其实我们还可以进行动态sql修改,有数据就修改

public class ReturnSql{
    //定义方法,返回查询的sql语句
    public String getUpdate(Student stu){
        return new SQL(){
            {
                UPDATE("student"); 表名
                if(stu.getName()!=null){
                    SET("name=#{name}");
                }
                //这个时候就算测试类中写的是null也不会报错
                if(stu.getAge()!=null){
                    SET("age=#{age}"); 修改数据
                }
                
                WHERE("id=#{id}") 条件
            }
        }.toString();
    }
}

删除操作

@DeleteProvider:生成删除用的SQL语句注解

public class ReturnSql{
    //定义方法,返回查询的sql语句
    public String getDelete(Integer id){
        return new SQL(){
            {
                DELETE_FROM("student"); 表名
                WHERE("#{id}");根据id来删除
            }
        }.toString();
    }
}

映射接口StudentMapper

public interface StudentMapper{
    //查询全部 不再使用这种形式了
    //@Select("SELECT * FROM student")
    //功能类和具体的方法   
    @SelectProvider(type=ReturnSql.class,method="getSelectAll")
    public abstract List<Student> selectAll();
    -----------------------------------------------------------
    @InsertProvider(type=ReturnSql.class,method="getInsert")
    public abstract Integer insert(Student,stu)

    @UpdateProvider(type=ReturnSql.class,method="getUpdate")
    public abstract Integer update(Student stu)

    @DeleteProvider(type=ReturnSql.class,method="getDelete")
        public abstract Integer delete(Integer id)
}

测试类

测试类里的内容和之前的一模一样

综合案例:学生管理系统

user数据表

图片.png

student数据表

图片.png

创建config.properties配置文件

图片.png

核心配置文件

引入配置文件和配置数据库环境、以及映射关系(dao的全路径目录)

图片.png

图片.png

持久层 学生接口

删除了接口实现类,用代理实现

StudentDao:

图片.png

StudentServiceImpl

图片.png

图片.png

图片.png

图片.png

图片.png