单表的CURD操作(使用mapper动态代理)

来源:互联网 发布:怎样注册一个域名 编辑:程序博客网 时间:2024/06/15 16:14

单表的CURD操作(使用mapper动态代理)

MyBatis框架抛开dao的实现类,直接定位到映射文件mapper的相应sql语句,对DB进行操作。这种dao的实现方式成为mapper的动态代理方式。

mapper动态代理方式无需程序员实现dao接口。接口是由MyBatis结合映射文件自动生成的动态代理实现的。

1.映射文件的namespace属性值

一般情况下,一个dao接口的实现类方法使用的是同一个sql映射文件中的sql映射id。所以,MyBatis框架要求,将映射文件中标签的namespace属性设为dao接口的全类名,则系统会根据方法所属dao接口,自动到相应namespace的映射文件中查找相关的sql映射。

简单来说,通过接口名即可定位到映射文件mapper。

2.修改日志输出控制文件

mapper的namespace修改了,则需要将日志输出控制文件中的logger的输出对象进行修改

##define a logger#log4j.logger.namespace_value=trace,consolelog4j.logger.com.hcx.dao.IStudentDao=trace,console

3.dao接口方法名

MyBatis框架要求,接口中的方法名,与映射文件中相应的sql标签的id值相同。系统会自动根据方法名到相应的映射文件中查找同名的sql映射id。

简单来说,通过方法名就可定位到映射文件mapper中相应的sql语句。

接口:

public interface IStudentDao {    int insertStudent(Student student);     void deleteStudentById(int id);    void updateStudent(Student student);    List<Student> selectAllStudents();    Map<String, Object> selectAllStudentsMap();    Student selectStudentById(int id);    List<Student> selectStudentsByName(String name);}

映射:

<select id="selectStudnetById" parameterType="int" resultType="com.hcx.beans.Student">    select id,name,age,score,birthday from student where id=#{id}</select>

4.dao对象的获取

使用时,只需要调用Sqlsession的getMapper()方法,即可获取指定接口的实现类对象。该方法的参数为指定dao接口类的class值。

session = factory.openSession();dao = session.getMapper(IStudentDao.class);

5.删除dao实现类

由于通过调用dao接口的方法,不仅可以从sql映射文件中找到所要执行sql语句,还可通过方法参数及返回值,将sql语句的动态参数传入,将查询结果返回。所以,dao的实现工作,完全可以由MyBatis系统自动根据映射文件完成。所以,dao的实现类就不再需要了。

dao实现对象是由jdk的proxy动态代理自动生成的。

6.测试类

1.在before注解方法中获取到Sqlsession对象后,通过Sqlsession的getMapper方法创建dao接口实现类的动态代理对象。在after注解方法中关闭Sqlsession对象。

public class MyTest {    private IStudentDao dao;    private SqlSession session;    @Before    public void setUp(){        session = MyBatisUtils.getSqlSession();        dao = session.getMapper(IStudentDao.class);    }    @After    public void tearDown(){        if(session!=null){            session.close();        }    }}

2.添加Sqlsession的提交方法

在增删改测试方法的最后,添加Sqlsession的commit方法,完成提交。

@Testpublic void test01(){    Student student = new Student("张三",23,99.8);    dao.insertStudent(student);    session.commit();}@Testpublic void test02(){    Student student = new Student("张三",23,99.8);    dao.insertStudentCatchId(student);    System.out.println("student="+student);    session.commit();}@Testpublic void test03(){    dao.deleteStudentById(3);       session.commit();}

3.删除selectStudentMap()方法测试

MyBatis框架对于dao查询的自动实现,底层只会调用selectOne与selectList()方法。而框架选择方法的标准是测试类中用户接收返回值得对象类型。若接收类型为list,则自动选择selectList()方法;否则,自动选择selectOne()方法。

接收类型为map,所以框架选择了selectOne()方法,会报错。

7.多查询条件无法整体接收问题的解决

在实际工作中,表单中所给出的查询条件有时是无法将其封装为一个对象的,也就是说,查询方法只能携带多个参数,而不能携带将着这多个参数进行封装的一个对象。对于这个问题,有两种解决方案。

方案一:将这多个参数封装为一个map

将这多个参数封装为一个Map

动态SQL

动态sql,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行查询。提交的查询条件不同,执行的sql语句不同。若将每种可能的情况均逐一列出,对所有条件进行排列组合,将会出现大量的sql语句。此时,可使用动态sql来解决这样的问题

用户自定义查询.PNG

动态sql,即通过MyBatis提供的各种标签对条件作出判断以实现拼接sql语句

这里的条件判断使用的表达式为OGNL表达式。常用的动态SQL标签有、、、等。

1.实体类:

public class Student {    private Integer id;    private String name;    private int age;    private double score;    //无参构造器与带参构造器    //getter 和 setter    //toString()}

2.测试类

public class MyTest {    private IStudentDao dao;    private SqlSession session;    @Before    public void setUp(){        session = MyBatisUtils.getSqlSession();        dao = session.getMapper(IStudentDao.class);    }    @After    public void tearDown(){        if(session!=null){            session.close();        }    }}

注意事项:

在mapper的动态sql中若出现大于号(>)、小于号(<)、大于等于号(>=)、小于等于号(<=)等符号,最好将其转换为实体符号。否则,xml可能会出现解析出错问题。

替换规则.PNG

1.标签

对于该标签的执行,当test的值为true时,会将其包含的sql片段拼接到其后所在的sql语句中。

例:查询出满足用户提交查询条件的所有学生。用户提交的查询条件可以包含一个姓名的模糊查询,同时还可以包含一个年龄的下限。当然,用户在提交表单时可能两个条件均作出了设定,也可能两个条件均不做设定,也可以只做其中一项设定。

查询条件不确定,查询条件依赖于用户提交的内容。此时,就可使用动态sql语句,根据用户提交内容对将要执行的sql进行拼接。

dao接口:

public interface IStudentDao {          List<Student> selectStudentsIf(Student student) }

映射文件:

<select id="selectStudentsIf" resultType="Student">    select * from student    where 1=1    <if test="name !=null and name!=''">        and name like '%' #{name} '%'    </if>    <if test="age > 0">        and age > #{age}    </if></select>

测试类:

@Testpublic void test01(){    Student student = new Student();    List<Student> students = dao.selectStudentsIf(student);    System.out.println(students);}

2.标签

dao接口:

public interface IStudentDao {    List<Student> selectStudentsIf(Student student);    List<Student> selectStudentsWhere(Student student);}

映射文件:

<select id="selectStudentsWhere" resultType="Student">    select * from student    <where>        <if test="name!=null and name!=''">            and name like '%' #{name} '%'        </if>        <if test="age > 0">            and age > #{age}        </if>    </where></select>

测试:

@Testpublic void test02(){    Student student = new Student();    List<Student> students = dao.selectStudentsWhere(student);    System.out.println(students);}

3.标签

该标签只可以包含,可以包含多个与一个。他们联合使用,完成java中的开关语句switch..case功能。

需求:若姓名不空,则按姓名查询;若姓名为空,则按年龄查询;若没有查询条件,则没有查询结果。

dao接口:

public interface IStudentDao {    List<Student> selectStudentsIf(Student student);    List<Student> selectStudentsWhere(Student student);    List<Student> selectStudentsChoose(Student student);}

映射文件:

对于标签,其会从第一个开始逐个向后进行条件判断。若出现中的test属性值为true的情况,则直接结束标签,不再向后进行判断查找。若所有的test判断结果均为false,则最后会执行标签。

<select id="selectStudentsChoose" resultType="Student">    select * from student    <where>        <choose>            <when test="name!=null and name!=''">                and name like '%' #{name} '%'            </when>            <when test="age>0">                and age < #{age}            </when>            <otherwise>                and 1 != 1            </otherwise>        </choose>    </where></select>

测试类:

@Testpublic void test03(){    Student student = new Student();    List<Student> students = dao.selectStudentsChoose(student);    System.out.println(students);}

4.标签–遍历数组

标签用于实现对于数组于集合的遍历。对其使用,需要注意:

  • collection表示要遍历的集合类型,这里是数组,即array
  • open、close、separator为对遍历内容的SQL拼接

dao接口:

public interface IStudentDao {    List<Student> selectStudentsIf(Student student);    List<Student> selectStudentsWhere(Student student);    List<Student> selectStudentsChoose(Student student);    List<Student> selectStudentsForeachArray(Object[] studentIds);}

映射文件

动态sql的判断中使用的都是OGNL表达式。OGNL表达式中的数组使用array表示,数组长度使用array.length表示。

<select id="selectStudentsForeachArray" resultType="Student">    select * from student    <if test="array !=null and array.length >0">        where id in        <foreach collection="array" open="(" close=")" item="myid" separator=",">            #{myid}        </foreach>    </if></select>

foreach标签.PNG

测试类:

@Testpublic void test04(){       Object[] studentIds = new Object[]{1,3};    List<Student> students = dao.selectStudentsForeachArray(studentIds);    System.out.println(students);}

5.标签–遍历泛型为基本类型的List

dao接口:

public interface IStudentDao {    List<Student> selectStudentsIf(Student student);    List<Student> selectStudentsWhere(Student student);    List<Student> selectStudentsChoose(Student student);    List<Student> selectStudentsForeachArray(Object[] studentIds);    List<Student> selectStudentsForeachList(List<Integer> studentIds);}

映射文件:

OGNL表达式中的List使用list表示,其大小使用list.size表示。

<select id="selectStudentsForeachList" resultType="Student">    select * from student    <if test="list!=null and list.size > 0">        where id in        <foreach collection="list"  open="(" close=")" item="myid" separator=",">            #{myid}        </foreach>    </if></select>

测试类:

@Testpublic void test05(){    List<Integer> studentIds = new ArrayList<Integer>();    student.add(1);    student.add(3);    List<Student> students = dao.selectStudentsForeachList(studentIds);    System.out.println(students);   }

6.标签–遍历泛型为自定义类型的List

dao接口:

List<Student> selectStudentsForeachList2(List<Student> students);

映射文件:

注意,这里的当前遍历对象类型是List中的泛型,即是Student对象。

<select id="selectStudentsForeachList2" resultType="Student">    <!-- select * from student where id in(1,3) -->    select * from student    <if test="list!=null and list.size > 0">        where id in        <foreach collection="list"  open="(" close=")" item="stu" separator=",">            #{stu.id}        </foreach>    </if></select>

测试类:

@Testpublic void test09(){    Student student1 = new Student();    student1.setId(1);    Student student3 = new Student();    student3.setId(3);    List<Student> students = new ArrayList<Student>();    students.add(student1);    students.add(student3);    students = dao.selectStudentsForeachList2(students);    System.out.println(students);}

7.标签

标签用于定义sql片段,以便其它sql标签复用。而其他标签使用该SQL片段,需要使用子标签。该标签可以定义SQL语句中的任何部分,所以子标签可以放在动态sql的任何位置

dao接口:

List<Student> selectStudentsBySQLFragment(List<Student> students);

映射文件:

使用sql片段.PNG

测试类:

@Testpublic void test09(){    Student student1 = new Student();    student1.setId(1);    Student student3 = new Student();    student3.setId(3);    List<Student> students = new ArrayList<Student>();    students.add(student1);    students.add(student3);    students = dao.selectStudentsBySQLFragment(students);    System.out.println(students);}