经过前面两章的学习,我们了解了如何使用MyBatis框架对数据表的数据进行增删改查,没有看过前面两章的小伙伴,你可以进我的头条号,里面有的。
大家可以看出,前面的CRUD操作基于的是XML配置文件的方式,重点是xxxMapper.xml文件的编写,其中定义了sql语句,定义了参数类型,返回值等等,有些人不太习惯于这种方式,既然是编程,一直配来配去总觉得有点不爽。那么能不能不写xxxMapper.xml文件呢?肯定是可以的,学过框架的都应该知道,除了使用配置文件,另外一种常见的方式就是注解(Annotation),或者两者结合起来使用,至于配置文件和注解的优缺点这里我就不去说明了,大家可以学完注解之后,可以自己感受一下两者的优势和劣势。OK,接下来咱们就使用注解的方式实现一下前面的增删改查,话不多说,步骤开启,不过在此之前,我们把前面的基于配置文件的步骤拿过来,对比才能加深印象。
1.新建一个Java项目,名称为"ES9D_MyBaits3",并且导入相应的jar包,如下图所示
2.编写SqlMapConfig.xml文件
what?不是说基于注解吗?怎么还写配置文件?注意,这里是Mybatis的核心配置文件,该文件不能缺省,我们所说的基于注解的方式,是对一个个Mapper.xml文件而言。该文件前面写过很多次,里面主要是配置数据源以及管理Mapper.xml文件等。
3.之前是编写xxxMapper.xml文件,这里咱们换成注解的方式,怎么做呢?
咱们先来想想看,既然在mapper文件中,编写了sql语句,定义了参数类型返回值等,并且这些操作是有意义的,因为它们对应了JDBC操作数据库的某些步骤,那么无论我们使用配置文件还是注解,这些步骤不能少。也就是说,虽然用注解的方式,但是原理是一样的,其实是相当于把在配置文件中做得事情搬个家,搬到注解上来。
那怎么搬?注解大家应该都用过,或者见过,既然要用注解,肯定得有地方能够写注解,在哪写呢?没错,在类中,所以看下面的做法,咱们定义一个接口(接口也是类,这个好理解吧?),名称为"UserMapperI"。为啥命名为这个呢?之前咱们说,既然要对数据表进行操作,比如咱们的t_users表,那么该张表就对应一个userMapper.xml文件,所有对该表进行的增删改查语句全部写到userMapper.xml文件中,那么用注解的方式也是一样,所以原理和前面使用配置文件方式的命名规则一样,后面的"I"表示接口"Interface",这样可读性是不是非常好?好了,扯了这么多,咱们把这个接口写出来,并且写上一些内容再分析。与此同时,咱们把实体类User也先建好。
然后还是以根据id查询某条记录为例,咱们还是类比,把之前在userMapper.xml文件中的select标签拿过来看下
resultType="com.es9d.domain.User">
select * from t_users where id=#{id}
那在UserMapperI中怎么写呢?
select标签对应@Select
中间的sql语句写到@Select("select * from users where id=#{id}")中,这点好理解,#{id}还是表示占位符
select标签中的id对应接口中的方法,方法名为"getUser"
select标签中的resultType对应方法的返回值
select标签中的parameterType对应方法的参数类型,所以该方法的声明为public User getUser(int id);
综上所述,得到下图
要朝这java程序员发展或者真心有兴趣的。可以找我要一些java的学习视频Java学习交流群:450936584,这个是免费的,希望同学找我要的时候不要有理所应当的态度,毕竟都是我的心血,希望你是真的有一颗想要学好java的心,我也会尽所能的去帮助你成为一名优秀的程序员。
4.之前需要将userMapper.xml交给核心配置文件SqlMapConfig管理,那么接口UserMapperI是否也一样呢?答案是肯定的,不然无效。
5.根据核心配置文件拿到SessionFactory对象从而获得Session对象,所以咱们把之前的工具类直接拿过来用,这里咱们就不多说咯,之前的两章都详细说过该工具类。
6.得到Session对象之后怎么做?
之前配置文件的方式,是构建出一个sql标识符,这个标识符的作用是定位到userMapper.xml文件中具体的某个标签,比如select标签对应的id值getUser,然后调用session的相应方法,传入该标识符以及所需要的参数值即可执行select标签对中的sql语句,得到对应的结果,如下图所示。
同理,咱们使用注解的方式,重点是UserMapperI接口,并且要执行其中的方法,是不是得先定位,就像配置文件的方式使用sql标识符进行定位一样,那咱们也定义一个字符串?比如String statement="com.es9d.mapper.annotation.UserMapperI.getUser",这样能行吗?这种适合配置文件的方式,然后用反射进行实现。咱们想想,在Java开发中,要想执行一个类中的方法,是不是得先new出对象(静态方法除外),然后对象.方法名进行执行,没问题吧?比如有一个Person类,其中有一个say的方法
class Person{
public void say(){
System.out.println("hello mybatis");
}
}
我们要想执行say这个方法,是不是得先Person p=new Person();
然后p.say(),很好理解吧?
那我们继续看,在UserMapperI接口中的getUser方法是否为静态的,显然不是,所以一定得new对象吧?但是这里有个问题是,UserMapperI是接口,接口可以new吗?显然不行,一般接口是怎么做的?我们需要创建一个类,去实现该接口,然后new出该接口的子类对象,从而调用其中的方法吧?还是举个例子
public interface Animal{
public void say();
}
要想执行其中的say方法,显然不能直接new Animal,因为Animal是接口,咱们得用一个类去实现它
class Dog implements Animal{
public void say(){
System.out.println("汪汪");
}
}
然后new Dog().say()。
所以对于我们的UserMapperI也是一样,需要一个实现类,好了,那咱们写一个实现类?不需要,MyBatis会帮我们自动构建出来,我们只需要直接用即可,代码如下
SqlSession session = MyBatisUtil.getSqlSession(true);
UserMapperI mapper = session.getMapper(UserMapperI.class);
其中这句话就是MyBatis帮我们自动构建出来的接口UserMapperI的实现类对象
至于UserMapperI为什么能够指向该实现类对象,是Java基础多态方面的知识,这里我就不展开叙述咯,不然就成了讲解Java基础了,基础不太了解的同学可以关注下我们的《Java快速入门》课程。
7.调用接口UserMapperI的getUser方法,整体代码如下
运行结果
8.前面是根据id进行查询的,那么增删改以及全部查询呢?实际上是一样的,这里我以增加为例,演示一下,直接上图
(1)在UserMapperI中添加注解以及方法
(2)使用JUnit测试
运行之后,发现数据表中的数据并没有增加,为何?注意,之前我们说过,对于增删改,需要事务的提交,此时看下session对象,并不是自动提交事务,所以要么手动提交事务,要么把session改成自动提交型的,这里我们手动提交一下事务。
(3)运行结果
对于其他的操作,大家可以自己试下,比较简单在,这里我就不一一演示咯,如果有什么问题欢迎一起讨论!看完感觉还可以,可以加一下我的群,上面我相信大家都看到了。