前言:
小伙伴们,大家好,我是狂奔の蜗牛rz,当然你们可以叫我蜗牛君,我是一个学习Java半年多时间的小菜鸟,同时还有一个伟大的梦想,那就是有朝一日,成为一个优秀的Java架构师。
这个Mybatis基础学习系列是用来记录我学习Mybatis框架基础知识的全过程 (这个系列是参照B站狂神的Mybatis最新教程来写的,由于是之前整理的,但当时没有发布出来,所以有些地方可能有错误,希望大家能够及时指正!)
之后我将尽量以两天一更的速度更新这个系列,还没有学习Mybatis3框架的小伙伴可以参照我的博客学习一下;当然学习过的小伙伴,也可以顺便跟我一起复习一下基础。最后,希望能够和大家一同进步吧!加油吧!少年们!
特别提醒:如果对Mybatis基础学习系列感兴趣,可以阅读本系列往期博客:
第一篇:Mybatis基础学习之初识Mybatis
第二篇:Mybatis基础学习之第一个Mybatis程序
第三篇:Mybatis基础学习之CRUD增删改查
第四篇:Mybatis基础学习之万能的Map和模糊查询
第五篇: Mybatis基础学习之配置解析(上篇)
第六篇: Mybatis基础学习之配置解析(下篇)
第七篇: Mybatis基础学习之使用ResultMap解决字段名不一致
第八篇: Mybatis基础学习之日志工厂的简单使用
第九篇: Mybatis基础学习之数据分页的简单使用
今天我们来到了Mybatis基础学习的第九站:使用注解开发。废话不多说,让我们开始今天的学习内容吧。
在之前的Java基础学习中,我们都知道Java语言一门面向对象的编程语言,很多相关书籍和资深程序员也会经常强调面向对象编程的重要性。在Java基础学习中,我们也接触到了接口的概念,而在真正的开发中,很多时候也会选择面向接口编程,那么为什么要选择面向接口编程呢?
选择面向接口的根本原因是:
在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的;这种情况下,各个对象内部是如何实现相对来说就不那么重要了。
而各个对象之间的协作关系成为系统设计的关键,小到不同类之间的通信,大到各模块之间的交互,这不仅是在设计之初需要着重考虑的,也是系统设计的主要工作内容,而面向接口编程就是指按照这种思想来编程。
接口从更深层次的理解,应是定义 (规范和约束) 与实现 (名实分离) 的分离
接口的本身反映了系统设计人员对系统的抽象理解
接口应有两类:
第一类:对一个个体的抽象,它可对应成为一个抽象体(abstract class)
第二类:对一个个体某一方面的抽象,即形成一个抽象面(interface)
一个个体可能有多个抽象面,抽象体和抽象面是有区别的
本质:反射机制实现
底层:动态代理
// User实体类
public class User {
private int id; // 用户编号
private String name; // 用户名
private String password; // 密码
// User实体类的无参构造方法
public User() {
}
// User实体类的有参构造方法
public User(int id, String name, String password) {
this.id = id;
this.name = name;
this.password = password;
}
/**
* 字段对应的get和set方法
*/
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
// 生成对应的toString方法
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
/**
* SqlSessionFactoryBuilder (建造工厂)
* --> sqlSessionFactory (生产sqlSessio)
* --> sqlSession
*/
public class MybatisUtils {
// 获取静态变量sqlSessionFactory
private static SqlSessionFactory sqlSessionFactory;
// 静态方法体
static {
try {
String resource = "mybatis-config.xml";
// 读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
// 获取工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* SqlSession提供了在数据库执行SQL命令所需的所有方法
*/
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
}
public interface UserMapper {
/**
* 使用Select注解: 查询所有用户信息
*/
@Select("Select * from user")
List<User> getUsers();
}
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
pwd=123456
注意:我们必须要将接口注册绑定到我们的核心配置文件中!
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties">properties>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
settings>
<typeAliases>
<package name="com.kuang.pojo"/>
typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${pwd}"/>
dataSource>
environment>
environments>
<mappers>
<mapper class="com.kuang.dao.UserMapper"/>
mappers>
configuration>
public class UserMapperTest {
@Test
public void test() {
// 获取sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 获取mapper接口类: 底层主要使用反射,通过反射来获取包的全类名
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//调用getUsers方法
List<User> users = mapper.getUsers();
// 使用foreach循环遍历数组
for (User user : users) {
System.out.println(user);
}
// 关闭sqlSession
sqlSession.close();
}
}
结果:虽然测试成功,并没有报错,但仔细观察结果后发现password的值却为null!
优点:使用注解来映射简单语句,会使代码显得更加简洁
缺点:对于稍微复杂一点的语句,Java注解就力不从心了,并且会显得更加混乱
因此,如果需要完成很复杂的事情,最好使用xml来映射语句
通过sqlSession获取变量后,mapper再次获取调用sqlSession,而mapper中的mapperInterface就是mapper接口,在mapperInterface下找到了com.kuang.dao.UserMapper
sqlSession:拿到数据库配置
mapperInterface:获取接口对象
methodCache:缓存
/**
* SqlSessionFactoryBuilder (建造工厂)
* --> sqlSessionFactory (生产sqlSessio)
* --> sqlSession
*/
public class MybatisUtils {
// 获取静态变量sqlSessionFactory
private static SqlSessionFactory sqlSessionFactory;
// 静态方法体
static {
try {
String resource = "mybatis-config.xml";
// 读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
// 获取工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* SqlSession 提供了在数据库执行 SQL 命令所需的所有方法
*/
public static SqlSession getSqlSession() {
// 设置参数为true,实现自动提交
return sqlSessionFactory.openSession(true);
}
}
public interface UserMapper {
/**
* 使用Select注解:通过id查询指定用户信息
* 方法存在多个参数,所有的参数前面必须加上 @Param("属性名") 注解
*/
@Select("Select * from user where id = #{id}")
User getUserById(@Param("id") int id);
}
public interface UserMapper {
/**
* 使用Select注解:通过查询指定用户信息
* 方法存在多个参数,所有的参数前面必须加上 @Param("属性名") 注解
*/
@Select("Select * from user where id = #{id}")
User getUserById(@Param("id") int id2);
}
public interface UserMapper {
/**
* 使用Select注解:通过查询指定用户信息
* 方法存在多个参数,所有的参数前面必须加上 @Param("属性名") 注解
*/
@Select("Select * from user where id = #{id}")
User getUserById(@Param("id2") int id);
}
public class UserMapperTest {
@Test
public void getUserById() {
// 获取sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 获取mapper接口类(底层主要使用反射,通过反射来获取包的全类名)
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 调用getUserById方法获取用户信息
User userById = mapper.getUserById(1);
// 打印查询到的用户信息
System.out.println(userById);
// 关闭sqlSession
sqlSession.close();
}
}
测试结果报错:参数id找不到!
结果:测试成功!
因此,@Select注解中的id与@Param注解中的id要一致!
public interface UserMapper {
/**
* 使用Insert注解:增加用户信息
*/
@Insert("Insert into user(id,name,pwd) values(#{id},#{name},#{password})")
int addUser(User user);
}
public class UserMapperTest {
@Test
public void addUser() {
// 获取sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 获取mapper接口类:底层主要使用反射,通过反射来获取包的全类名
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 调用addUser方法并设置返回的结果集:实现用户信息的增加
int result = mapper.addUser(new User(6,"陈奕迅","cyx123456"));
// 判断结果集的值是否大于0
if (result>0) {
System.out.println("插入成功!");
}
// 关闭sqlSession
sqlSession.close();
}
}
结果:成功插入一条用户信息!
因为在Mybatis工具类中已经设置了自动提交事务,因此测试方法中就不需要再次设置了,但是一般不建议设置自动提交事务,因为这样容易出现错误!
public interface UserMapper {
/**
* 使用Update注解:修该指定用户信息
*/
@Update("Update user set name = #{name},pwd = #{password} where id = #{id}")
int updateUser(User user);
}
public class UserMapperTest {
@Test
public void updateUser() {
// 获取sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 获取mapper接口类(底层主要使用反射,通过反射来获取包的全类名)
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 调用updateUser方法, 实现插入用户信息
mapper.updateUser(new User(6,"张惠妹","zhm123456"));
// 关闭sqlSession
sqlSession.close();
}
}
结果:成功更新一条用户信息!
public interface UserMapper {
/**
* 使用Delete注解:删除用户信息
* @Delete注解中的uid要与@Param注解中的uid一致
*/
@Delete("Delete from user where id = #{uid}")
int deleteUser(@Param("uid") int id);
}
public class UserMapperTest {
@Test
public void deleteUser() {
// 获取sqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 获取mapper接口类(底层主要使用反射,通过反射来获取包的全类)
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 调用updateUser方法, 实现插入用户信息
mapper.deleteUser(4);
// 关闭sqlSession
sqlSession.close();
}
}
结果:成功删除id为4的用户信息!
好了,今天的有关 使用注解开发 的学习就到此结束啦。欢迎小伙伴们积极学习和讨论,喜欢的可以给蜗牛君点个关注,顺便来个一键三连。我们下期见,拜拜啦!
参考视频链接:【狂神说Java】Mybatis最新完整教程IDEA版通俗易懂