飞道的博客

JavaWeb——MyBatis框架之入门总结及案例实战,常见坑处理:Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.0.0

423人阅读  评论(0)

目录

1 引导

2 MyBatis框架入门

2.1 MyBatis环境搭建

2.2 MyBatis入门案例实战

2.2.1 MyBatis读取数据库的入门案例实战

2.2.2 入门案例设计模式分析

2.2.3 MaBatis基于注解的入门案例


1 引导

框架的概念在以前的博文中也有提到,此处简单说明下,框架实质是软件开发中的一套解决方案,不同的框架解决的是不同的问题。

1)使用框架的好处:框架封装了很多细节,开发者可以很简单的实现某些功能,提高开发效率

2)框架解决了什么问题?

看下三层架构和SSM框架的对应关系,MyBatis框架是解决的持久层的问题,与数据库交互,进行增删改查操作的。

3)持久层技术解决方案有哪些?

  • JDBC技术:Connection、PreparedStatement、ResultSet;
  • Spring的JdbcTemplate:Spring对Jdbc的简单封装;
  • Apache的DBUtils,和Spring的JdbcTemplate类似,也是对Jdbc的简单封装;

以上都不是框架,JDBC是规范,后两者都只是工具类,是对规范的实现,没有系统的解决方案。

以前使用传统jdbc的步骤很多,操作繁杂,我们要实现一个需求的功能,从数据库表中查找一个结果,希望没有这么多繁杂的操作步骤,把焦点放在功能的实现上即可,实现高效率开发,MyBatis框架就是帮我们解决这些问题的。

2 MyBatis框架入门

MyBatis是一个基于Java的持久层框架,封装了jdbc操作的细节,开发者只需要关注sql语句本身,不需要关注注册驱动、创建连接、创建statement等过程,它使用了ORM思想实现了结果集封装。

注:ORM,Object Relational Mapping对象关系映射,就是把数据库表和实体类的属性对应起来,让我们可以操作实体类就可以操作数据库表。我们需要保证实体类属性和数据库表的字段名称保持一致,有一个好习惯;

2.1 MyBatis环境搭建

下面以一个案例形式一步步看下如何搭建MyBatis环境。

1)准备数据库,在本地数据库db4中新建一个user表,插入数据:


  
  1. CREATE DATABASE db4;
  2. USE db4;
  3. CREATE TABLE USER (
  4. id INT( 11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  5. username VARCHAR( 32) NOT NULL COMMENT '用户名称',
  6. birthday DATETIME DEFAULT NULL COMMENT '生日',
  7. sex VARCHAR( 1) DEFAULT NULL COMMENT '性别',
  8. address VARCHAR( 256) DEFAULT NULL COMMENT '地址'
  9. ) ENGINE= INNODB DEFAULT CHARSET=utf8;
  10. INSERT INTO `user`( `id`, `username`, `birthday`, `sex`, `address`) VALUES ( 1, '老王', '2018-02-27 17:47:08', '男', '北京'),( 2, '李四', '2018-03-02 15:09:37', '女', '上海'),( 3, '王五', '2018-03-04 11:34:34', '女', '南京');

2)新建Maven工程,不使用模板,此处不展开了,需要回顾的可以看上一篇博文

3)配置pom.xml文件,导入相关的jar包坐标:


  
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation= "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0 </modelVersion>
  6. <groupId>com.winter </groupId>
  7. <artifactId>19.mybatis </artifactId>
  8. <version>1.0-SNAPSHOT </version>
  9. <packaging>jar </packaging>
  10. <dependencies>
  11. <dependency>
  12. <groupId>org.mybatis </groupId>
  13. <artifactId>mybatis </artifactId>
  14. <version>3.4.5 </version>
  15. </dependency>
  16. <dependency>
  17. <groupId>mysql </groupId>
  18. <artifactId>mysql-connector-java </artifactId>
  19. <version>5.1.6 </version>
  20. </dependency>
  21. <dependency>
  22. <groupId>log4j </groupId>
  23. <artifactId>log4j </artifactId>
  24. <version>1.2.12 </version>
  25. </dependency>
  26. <dependency>
  27. <groupId>junit </groupId>
  28. <artifactId>junit </artifactId>
  29. <version>4.10 </version>
  30. <scope>test </scope>
  31. </dependency>
  32. </dependencies>
  33. </project>

4)写一个User实体类,实现Serializable,数据库表对应


  
  1. public class User implements Serializable {
  2. private Integer id;
  3. private String username;
  4. private Date birthday;
  5. private String sex;
  6. private String address;
  7. public Integer getId() {
  8. return id;
  9. }
  10. public void setId(Integer id) {
  11. this.id = id;
  12. }
  13. public String getUsername() {
  14. return username;
  15. }
  16. public void setUsername(String username) {
  17. this.username = username;
  18. }
  19. public Date getBirthday() {
  20. return birthday;
  21. }
  22. public void setBirthday(Date birthday) {
  23. this.birthday = birthday;
  24. }
  25. public String getSex() {
  26. return sex;
  27. }
  28. public void setSex(String sex) {
  29. this.sex = sex;
  30. }
  31. public String getAddress() {
  32. return address;
  33. }
  34. public void setAddress(String address) {
  35. this.address = address;
  36. }
  37. @Override
  38. public String toString() {
  39. return "User{" +
  40. "id=" + id +
  41. ", username='" + username + '\'' +
  42. ", birthday=" + birthday +
  43. ", sex='" + sex + '\'' +
  44. ", address='" + address + '\'' +
  45. '}';
  46. }
  47. }

5)写一个User的持久层接口


  
  1. //User的持久层接口
  2. public interface UserDao {
  3. List<User> findAll();
  4. }

至此,准备工作OK了,下面看下MyBatis的环境。

6)在resources包下新建SqlMapConfig.xml文件作为MyBatis的主配置文件,其中做两件事:

  • 配置MySQL的环境:事务类型、连接池、四个基本信息(驱动、url、用户名、密码);
  • 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件;

  
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <!--mybatis的主配置文件 -->
  6. <configuration>
  7. <!--配置环境 -->
  8. <environments default="mysql">
  9. <!--配置mysql环境 -->
  10. <environment id="mysql">
  11. <!--配置事务类型 -->
  12. <transactionManager type="JDBC"> </transactionManager>
  13. <!--配置数据源(连接池) -->
  14. <dataSource type="POOLED">
  15. <!--配置连接数据库的四个基本信息 -->
  16. <property name="driver" value="com.mysql.jdbc.Driver"/>
  17. <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
  18. <property name="username" value="root"/>
  19. <property name="password" value="root"/>
  20. </dataSource>
  21. </environment>
  22. </environments>
  23. <!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
  24. <mappers>
  25. <mapper resource="com/winter/dao/UserDao.xml"> </mapper>
  26. </mappers>
  27. </configuration>

7)新建每个dao的独立配置文件,注意三件事:

  • 在resources包下新建com.winter.dao三级包(mybatis映射配置文件必须和dao接口的包结构相同),命名为UserDao.xml,和SqlMapConfig.xml中指定的名字要一致;
  • mapper标签下的namespace属性要是UserDao接口的全限定类名;
  • 操作配置(select标签中配置sql语句)中id属性要与UserDao接口中的方法名字一致;

  
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.winter.dao.UserDao">
  6. <!--配置查询所有 -->
  7. <select id="findAll">
  8. select * from user
  9. </select>
  10. </mapper>

映射配置文件中的限制很多,这么做的好处是什么呢?我们不需要再写dao的实现类了!(上述的独立配置文件还有点小问题,你发现了吗?没有的话继续阅读下文:)

完成以上后,工程目录结构如下:

2.2 MyBatis入门案例实战

2.2.1 MyBatis读取数据库的入门案例实战

在上一节环境搭建的基础上,我们看下如何使用MyBatis,使用的步骤是怎样的,可以总结为如下几个步骤:

  • 1)读取配置文件;
  • 2)创建SqlSessionFactory工厂;
  • 3)使用工厂生产SqlSession对象;
  • 4)使用SqlSession创建Dao接口的代理对象;
  • 5)使用代理对象执行方法;
  • 6)释放资源。

在src.test.java.com.winter.test包下新建一个测试类MyBatisTest.java:


  
  1. public class MyBatisTest {
  2. //MyBatis入门案例
  3. @Test
  4. public void test() throws Exception{
  5. //1、读取配置文件
  6. InputStream in = Resources.getResourceAsStream( "SqlMapConfig.xml");
  7. //2、创建SqlSessionFactory工厂
  8. SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
  9. SqlSessionFactory factory = builder.build(in);
  10. //3、使用工厂生产SqlSession对象
  11. SqlSession session = factory.openSession();
  12. //4、使用SqlSession创建Dao接口的代理对象
  13. UserDao userDao = session.getMapper(UserDao.class);
  14. // 5、使用代理对象执行方法
  15. List<User> users = userDao.findAll();
  16. for (User user : users) {
  17. System.out.println(user);
  18. }
  19. //6、释放资源
  20. session.close();
  21. in.close();
  22. }
  23. }

【运行测试】:发现如下异常问题出现:

### Error querying database.  Cause: org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the Mapped Statement 'com.winter.dao.UserDao.findAll'.  It's likely that neither a Result Type nor a Result Map was specified.

我们在UserDao.xml里面写了sql查询语句,但是MyBatis不知道查询结果要封装到哪里去,所以要在UserDao.xml中对应提供另一个指定的对象类型,修正后的UserDao.xml如下:


  
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.winter.dao.UserDao">
  6. <!--配置查询所有 -->
  7. <select id="findAll" resultType="com.winter.domain.User">
  8. select * from user
  9. </select>
  10. </mapper>

再次运行测试OK:

【小插曲——调试问题】:开始MyBatisTest中使用public static void main(String[] args)方法测试,但是运行时始终报错:

Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.0.0:exec (default-cli) on project 19.mybatis: Command execution failed.

网上查找各种解决方法,如项目的java版本配置和JDK要一致等等,最后都没解决,怀疑是Maven支持的JDK版本问题,我的是14.0.1,最后通过junit解决,@Test注解运行就可以了。

2.2.2 入门案例设计模式分析

基于上述案例,分析下设计模式。

1)读取配置文件

不建议使用绝对路径,或相对路径,不够灵活,实际项目中多使用以下两种:

  • 使用类加载器,它只能读取类路径的配置文件;
  • 使用ServletContext对象的getRealPath();

2)创建SqlSessionFactory工厂

MyBatis使用了构建者模式,把对象的创建细节隐藏,使用者直接调用方法即可获取对象。像我们自己盖厂房一样,不是事事亲为,我们找个包工队,告诉需求,给钱即可:

  • SqlSessionFactoryBuilder类似于包工队;
  • in类似于我们给的钱;

3)创建SqlSession对象

使用了工厂模式,降低了类之间的依赖关系

4)创建dao接口的代理对象

使用了代理模式,不修改源码的基础上对已有方法增强;

2.2.3 MaBatis基于注解的入门案例

以上基于xml的实现方式是不是感觉有些麻烦,映射配置文件有很多要对应的关系,下面来看下比较简单的方式,使用注解,相比于xml,主要改变在于:

  • 移除UserDao.xml,在dao接口的方法上使用@Select注解,并且指定SQL语句;
  • 在SqlMapConfig.xml中的mapper配置时,使用class属性指定dao接口的全限定类名。

【UserDao接口】:


  
  1. public interface UserDao {
  2. @Select("select * from user")
  3. List<User> findAll();
  4. }

【SqlMapConfig.xml中mapper配置】:


  
  1. <!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
  2. 若使用注解配置,应该使用class属性指定被注解的dao全限定类名
  3. -->
  4. <mappers>
  5. <mapper class="com.winter.dao.UserDao"> </mapper>
  6. </mappers>

【注意】:实际MyBatis也是支持写dao实现类的,但是实际开发中追求的理念就是越简单越好,无论是xml还是注解形式,一般都是不写dao实现类。

———————————————————————————————————

本文为博主原创文章,转载请注明出处!

若本文对您有帮助,轻抬您发财的小手,关注/评论/点赞/收藏,就是对我最大的支持!

祝君升职加薪,鹏程万里!


转载:https://blog.csdn.net/w464960660/article/details/108265369
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场