Maven创建Mybatis工程

2020-02-10  本文已影响0人  AxisX

1.mybatis概述

1.1 框架

框架是软件开发过程中的一套解决方案,不同框架解决不同问题,框架封装了很多细节,可以使开发者用极简的方式来实现项目。

三层架构与MVC设计模式目标一致,都是为了解耦合并提高代码复用,但是二者对于项目的理解角度不同。三层分别为:表示层(USL,User Show Layer:视图层)、业务逻辑层(BLL,Business Logic Layer:Service层)、数据访问层(DAL,Data Access Layer:Dao层)。上层依赖于下层(持有成员变量或需要有下层才能成立)


image.png

数据访问层技术包含:JDBC、Spring的JdbcTemplate(Spring中对jdbc的简单封装)、Apache的DBUtils。但这些都不是框架,JDBC属于规范,而Spring或Apache对应的内容都只是工具类。而MyBatis则属于数据访问层框架。(后续要说的Spring MVC 属于表示层框架),JDBC的内容可以参考之前的文章。其中的demo如下:

import java.sql.*;

public class JDBCDemo {
   static final String URL="jdbc:oracle:thin:@localhost:1521:ORC";
   static final String USERNAME="scott";
   static final String PWD="tiger";

   public static void update(){//增删改
       //a.导入驱动,加载具体的驱动类
       Connection connection=null;
       Statement stmt=null;
       ResultSet resultSet=null;
       try{
           Class.forName("oracle.jdbc.OracleDriver");
           //b.与数据库建立连接
           connection=DriverManager.getConnection(URL,USERNAME,PWD);

           //c.发送sql并执行
           // (1)Statement方式
           stmt=connection.createStatement();
           String sql="insert into Users values('zhangsan',18)";
           String query="select age,name from Users";
           resultSet=stmt.executeQuery(query);//resultSet为指向行的数据,.getXXX()获取对应类型数据
           int count=stmt.executeUpdate(sql);//执行增删改,返回值表示增删改了几条

           // (2)PrepareStatement方式(sql语句提前,可用?替代值),推荐使用此方法
           //在多运行条件下,sql编译一次,数据被执行N次。而Statement方式方式sql也需要被执行N次
           //此方式可以防止sql注入
           String sql2="insert into Users values(?,?)";
           PreparedStatement pstmt=connection.prepareStatement(sql2);//预编译
           pstmt.setString(1,"zhangsan");//set方法替换占位符
           pstmt.setInt(1,18);
           int count2=pstmt.executeUpdate();

           //(3)CallableSatatement方式(调用存储过程(无返回值,out代替)或存储函数(有返回值))
           //(?,?,?)前两个参数相加,第三个参数为输出参数,输出两个的和
           CallableStatement cstmt=connection.prepareCall("call addTwoNum(?,?,?)");
           cstmt.setInt(1,10);//set处理参数
           cstmt.setInt(2,10);
           cstmt.execute();
           //设置输出参数的类型
           cstmt.registerOutParameter(3,Types.INTEGER);
           int result=cstmt.getInt(3);

           //d.处理结果
           if(count>0){
               System.out.println("操作成功");
           }
           while(resultSet.next()){//next表示下移,判断下移之后是否有元素,有则为true,否则为false
               int age=resultSet.getInt("age");
               String name=resultSet.getString("name");
               //上面两行数据等价于如下两行,此对应编号从1开始,但推荐使用字段名而不是下标查询
               //int age=resultSet.getInt(1);
               //String name=resultSet.getString(2);

               System.out.println(name+""+age);
           }
       }
       catch(ClassNotFoundException | SQLException e){
           e.printStackTrace();
       }
       finally{
           try{
               if(resultSet!=null) resultSet.close();
               if(stmt!=null)stmt.close();//对象.方法,如果对象为空会报空指针
               if(connection!=null) connection.close();
               //先开的后关,后开的先关
           }
           catch (SQLException e){
               e.printStackTrace();
           }
       }
   }
   public static void main(String[] args){
       update();
   }
}

MyBatis基于java,采用了ORM(Object Relational Mapping对象关系映射)的思想,解决了实体和数据库映射的问题(如User类对应数据库的user表),对JDBC进行了封装,屏蔽了JDBC API底层访问细节。开发者只需要关注SQL语句,不需要再去写JDBC中加载驱动、创建连接、Statement等过程。MyBatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终的sql语句。

1.2 环境搭建与demo

创建Maven工程,接着创建实体类和dao接口,然后创建Mybatis的主配置文件(sqlMapConfig.xml),再创建映射文件(IUserDao.xml)在其中写增删改查等语句。最后写测试类,session.selectOne("需要查询的nmaespace.id","SQL参数值")
Maven工程,在IDEA创建新工程的方式选择maven,然后配置生成的pom.xml,内容如下。本文Mybatis工程连接的数据库是mysql, maven会根据<dependency>标签中的内容帮我们下载相应驱动。不用maven连接mysql数据库可以参考之前的文章进行对比。关于Maven的简单介绍及用法请见文章末尾。

//pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>02_10</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
<!--        使用mybatis用上述两个配置即可-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
    </dependencies>
</project>

(1)创建实体类User和对应接口IUserDao
在java文件夹下创建User、IUserDao代码如下

//IUserDao.java
package org.example.dao;
import org.example.domain.User;
import java.util.List;

//用户的数据访问层接口
public interface IUserDao {
    //查询所有操作
    List<User> findAll();
}
//User.java
package org.example.domain;
import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

(2)配置Mybatis

//sqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--    配置环境-->
    <environments default="mysql">
<!--        配置mysql环境-->
        <environment id="mysql">
<!--            配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
            <!-- 配置连接数据库的4个基本信息 -->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/javaweb"/>
                <property name="username" value="root"/>
                <property name="password" value=""/>
            </dataSource>
        </environment>
    </environments>
    <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
    <mappers>
        <mapper resource="org/example/dao/IUserDao.xml"/>
    </mappers>
</configuration>

MyBatis的映射配置文件位置必须和IUserDao一致,并且其mapper标签和namespace属性的取值要和Dao接口的全限定类名一致<mapper namespace="org.example.dao.IUserDao">
根据我们的项目所运行环境的不同,如本机、发布环境等,可以<environment id="mysql">通过id值不同进行不同配置,然后通过<environments default="mysql">default值去调用对应的id,选取相应的运行环境。运行环境的选取也可以在测试文件的SqlSessionFactoryBuilder().build(reader,"mysql");语句中指定。

transactionManager 事务提交方式除了用JDBC方式(commit、rollback、close),还可以用MANAGED,这个是将事务交由其他组件去托管(如,Spring),MANAGED在默认方式下会关闭连接。如果不想关闭需配置语句<property name="closeConnection" value="false"/>

dataSource的数据类型,除了demo中写的
<dataSource type="POOLED">POOLED代表使用数据库连接池,type还可以是UNPOOLED,
这个就是传统的JDBC模式,每次都需要打开、关闭数据库等。但是这种操作较为消耗性能。还可以是JNDI方式,这个是从tomcat中获取一个内置的数据库连接池(POOLED是第三方的,非tomcat自带)。一般dataSource用POOLED。

(3)在resources文件夹下创建IUserDao.xml(Mapper),和IUserDao接口二者名称相对应。

//IUserDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.dao.IUserDao">
    <!--配置查询所有-->
<!-- id为Dao中的方法名称-->
<!-- 此Dao一般也命名为Mapper-->
    <select id="findAll" resultType="org.example.domain.User" parameterType="int">
        select * from TestUsers
    </select>
</mapper>

namespace是该mapper.xml映射文件的唯一标识,在其他文件中定位此处sql的sql语句就用namespace.id的方式。parameterType代表输入参数类型,resultType代表查询返回结果类型。MyBatis理论上只接收一个传入值并只输出一个值,如果想变成多个值,需要把其换成类或对象的形式。
映射配置文件的操作配置(如select),其id属性的取值必须是Dao接口的方法名。
如果要往sql语句中传入sql,可以通过#{}。如果传入参数时简单类型(8个基本类型+String)那么可以使用任何形式占位符#{XXX},但如果是对象类型,则括号中必须是对象的属性#{属性名}。输出参数如果返回的是一个对象,无论是一个还是多个值,resultTyoe都是全限定类名。

    <select id="findAll" resultType="org.example.domain.User" parameterType="int">
        select * from TestUsers where id=#{id}
    </select>

增删改的方式如下:

    <insert id="add" parameterType="org.example.domain.User">
        insert into TestUsers(id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address})
    </insert>
    <update id="update" parameterType="org.example.domain.User">
        update TestUsers set id=#{id},username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
    </update>
    <delete id="deletebyid" parameterType="int">
        delete from TestUsers where id=#{id}
    </delete>

(4)建立测试文件MybatisTest
在test文件夹的java文件夹下,建立对应的测试文件夹结构org.example.test,目录下简历测试文件MybatisTest.java,其代码内容如下。

package org.example.test;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.*;
import org.example.domain.User;
import java.io.IOException;
import java.io.Reader;

public class MybatisTest {
    public static void main(String[] args) throws IOException {
        //1.读取配置文件
        Reader reader= Resources.getResourceAsReader("SqlMapConfig.xml");
        //2.创建SqlSessionFactor工厂
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);
        //3.使用工厂生产SqlSession对象并创建Dao接口的代理对象
        //session=JDBC的connection
        SqlSession session=sqlSessionFactory.openSession();
        //4.使用代理对象执行方法
        String statement="org.example.dao.IUserDao.findAll";
        User person = session.selectOne(statement);
        System.out.println(person);
        //5.释放资源
        session.close();
    }
}

完成后直接run即可看到运行图如下,成功从数据库中取出内容。如果需要往sql语句中传值,在执行方法时可以写成User person = session.selectOne(statement,1);,此处的1即为id=1

MybatisTest 运行效果图

如果是增删改,前三个步骤都不变,第四步骤使用代理对象执行方法改变部分如下:

//增
String statement="org.example.dao.IUserDao.add";
Date date=new Date();
User  users=new User(3,"wangwu",date,"男","黑龙江漠河");
int count = session.insert(statement,users);
session.commit();
//删
String statement="org.example.dao.IUserDao.deletebyid";
int count =session.delete(statement,3);
 session.commit();
System.out.println("删除了"+count+"个学生");
//改
String statement="org.example.dao.IUserDao.update";
Date date=new Date();
User user=new User();
user.setId(3);
user.setUsername("dududu");
user.setBirthday(date);
user.setSex("男");
user.setAddress("黑龙江漠河");
int count =session.update(statement,user);
session.commit();

1.3 Mapper动态代理方式(MyBatis接口开发)

配置方式在.xml中定义,硬编码是在.java中的定义。约定则是默认值。动态代理原则就是约定优于配置。与上节不同的是,动态代理方式约定的目标,可以省略掉statement,即根据约定直接定位出SQL语句。
既然是基于接口开发,首先要定义一个接口。接口的方法和IUserDao.xml(mapper)中SQL标签一一对应,且namespace的值是接口的全类名。
以删除为例,其Mapper文件如下

//IUserDao.java
public interface IUserDao {
      int deletebyid(int id);
}

注意,此处方法名和IUserDao.xml(mapper)文件中标签的id值相同,并且方法的输入参数和标签的parameterType类型一致,方法的输出参数(返回值)和标签resultType一致

    <delete id="deletebyid" parameterType="int">
        delete from TestUsers where id=#{id}
    </delete>

相应的在测试文件MybatisTest.java中将delUsers()函数原来为//后内容,改为接口形式如下:

//MybatisTest.java
// String statement="org.example.dao.IUserDao.deletebyid";
// int count =session.delete(statement,3);
IUserDao user= session.getMapper(IUserDao.class);
int count=user.deletebyid(3);

1.4 配置文件优化

(1)动态引入
SqlMapConfig.xml中数据库配置相关内容如下:

//SqlMapConfig.xml
<configuration>
        <!-- 配置连接数据库的4个基本信息 -->
                 <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/javaweb?characterEncoding=gbk"/>
                 <property name="username" value="root"/>
                <property name="password" value=""/>
</<configuration>

如果我们想动态的加载相应信息,可以创建一个db.properties放入配置文件,让SqlMapConfig.xml去调用此文件,从而动态引入。其文件内容如下:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/javaweb?characterEncoding=gbk
username=root
password=

SqlMapConfig.xml相应内容如下,是键值对的形式。

//SqlMapConfig.xml
<configuration>
    <properties resource="db.properties"/>
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
</<configuration>>

(2)全局参数
全局参数采用的标签是

//SqlMapConfig.xml
    <settings>
        <setting name="cacheEnabled" value="false" />
    </settings>

(3)别名

    <typeAliases>
<!--  单个别名(忽略大小写)-->
        <typeAlias type="org.example.domain.User" alias="User"/>
<!--    多个别名(别名就是不带包名的类名,忽略大小写)-->
        <package name="org.example.domain"/>
    </typeAliases>

2.Maven

2.1 Maven简介

Maven 翻译为"专家"、"内行",是 Apache 下的一个纯 Java 开发的开源项目。Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。也可应用于其他语言编写的项目,例如 C#,Ruby,Scala等。Maven是基于Java的自动化构建工具,说到自动化建构工具,按照发展历程讲有make、ant、Maven、Gradle等。Maven则是现在的主流。Maven的作用包括:管理Jar包,将项目拆分成若干个模块等。以管理jar文件为例,Maven可以增加第三方Jar,如commons-fileupload.jar ,commons-io.jar。也可以管理jar包之间的依赖关系,当我们导入一个包的时候,其他所需的依赖,Maven会自动关联下载。

2.2 Maven生命周期

Maven的构建(build)生命周期,从验证(validate)->编译(compile)->测试(Test)->包装(package)->检查(verify)->安装(install)->部署(deploy)
(1)验证
验证项目是否正确且所有必须信息是可用的
(2)编译
java->class
(3)测试
针对项目中的关键点进行测试,也可用项目中的测试代码去测试开发代码。使用适当的单元测试框架(例如JUnit)运行测试。将测试的结果以报告形式进行显示。
(4)包装
将项目中包含的多个文件压缩成一个文件,用于安装或部署(java项目—jar,web项目-war)
(5)检查
对集成测试的结果进行检查,以保证质量达标
(6)安装
将达成的包放到本地仓库供其他项目使用
(7)部署
拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程。
所以当我们执行其中的某个命令时,会把前面相应的步骤执行一遍。

除了上述的构建周期(default lifecycle),还有清理周期(clean lifecycle:pre-clean、clean、post-clean)和站点周期(site lifecycle:pre-site、site、post-site、site-deploy)。清理用于删除编译的结果,为重新编译做准备。采用命令mvn post-clean执行。

2.3 Maven的目录结构

Maven的目录结构

pom.xml配置的关键内容如下

 <groupId>大项目名</groupId>
 <groupId>com.jsoft.test</groupId>

 <artifactId>子模块名</artifactId>
 <artifactId>HelloWorld</artifactId>

 <version>版本号</version>
 <version>0.1-SNAPSHOT</version>

所有执行mvn的命令,必须在pom.xml所在目录中执行
maven常见命令如下:
mvn compile(只编译Main目录中的java文件)
mvn test (测试)
mvn package(打成jar/war)
mvn install(将开发的模块放入本地仓库)
mvn clean(删除target目录)

2.4 Maven仓库

首先要了解依赖的含义,加入common-fileupload.jar依赖于commons-io.jar即A中的某些类需要使用B中的某些类,就称为A依赖于B。Maven中如果要使用存在的jar或模块就可以通过依赖实现,去本地仓库或者中央仓库寻找。
仓库,是项目中依赖的第三方库所在的位置。在Maven中,任何一个依赖、插件或者项目构建的输出都可以称之为构件。而仓库就可以帮我们管理这些构件(主要是JAR),它就是放置所有JAR文件(WAR,ZIP,POM等等)的地方。Maven 仓库有三种类型:本地(local)、中央(central)、远程(remote)。本地仓库在第一次执行maven命令的时候被创建,maven所需的任何构件都是直接从本地仓库获取,如果本地没有,就尝试从远程仓库下载到本地仓库,然后再使用。Maven 中央仓库是由 Maven 社区提供的仓库,其中包含了大量常用的库。如果 Maven 在中央仓库中也找不到依赖的文件,它会停止构建过程并输出错误信息到控制台。为避免这种情况,Maven 提供了远程仓库的概念,它是开发人员自己定制仓库,包含了所需要的代码库或者其他工程中用到的 jar 文件。

Maven仓库
上一篇 下一篇

猜你喜欢

热点阅读