添加和使用MyBatis框架(动态代理)的步骤和说明

本文详细介绍了在Java项目中通过Maven添加MyBatis框架的步骤,包括新建Maven项目、配置pom.xml、添加数据库依赖、设置jdbc.properties属性文件、创建SqlMapConfig.xml和Mapper接口及XML文件。同时,文章还阐述了动态代理的实现规范,并讲解了#{ }和${ }占位符的使用、返回主键值、UUID、动态SQL以及指定参数位置的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

通过maven项目添加框架的具体步骤

以下为拓展延伸知识 


通过maven项目添加框架的具体步骤

1.新建maven项目

如果是做java项目(Artifact中)选择:maven-archetype-quickstart

如果是做web项目(Artifact中)选择:maven-archetype-webapp

2.修改目录,添加缺失的目录,修改目录属性

添加主程序的资源文件夹和测试程序的资源文件夹 :resources

3.修改pom.xml文件,添加myBatis的依赖,添加mysql的依赖

   <!--修改jdk版本 -->
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

    <!--mysql驱动 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.28</version>
    </dependency>

    <!--添加MyBatis框架的依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.9</version>
    </dependency>

4.修改pom.xml文件,添加资源文件的指定:主要作用是为了将所有主程序下的的资源文件都被拷贝下来

<!--添加资源文件的指定-->
  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.xml</include>
          <include>**/*.properties</include>
        </includes>
      </resource>

      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.xml</include>
          <include>**/*.properties</include>
        </includes>
      </resource>
    </resources>
  </build>

5.在idea中添加数据库的可视化 :主要是为了在后面的sql语句编写时的查看和操作

在idea  maven项目中的右侧提供了(database)数据库可视化操作

步骤:点击加号+  Data Aource(数据源) —>MySQL

这里需要注意,如果排查了信息填写有误的原因后,测试连接失败,需要查看mysql的版本是否正确,可点击边上的mysql重写选择正确的驱动版本

 6.在resources文件夹中添加jdbc.properties属性文件(数据库的配置)

jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/库名?useUnicode=true&amp&characterEncoding=UTF-8
jdbc.username=数据库用户名
jdbc.password=登录密码

 其中useUnicode=true&amp&characterEncoding=UTF-8是处理数据库出现乱码问题

7.添加SqlMapConfig.xml文件,MyBatis的系统核心配置文件

<?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>
    <properties resource="jdbc.properties"/>
    <!--读取属性文件(jdbc.properties)
    properties标签包含属性:
    resources:从resources目录下找指定名称的文件加载
    url:使用绝对路径加载属性文件
    -->
    <settings><!--设置日志输出底层执行的代码-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <typeAliases><!--注册实体类的别名  只能使用其中一种-->
        <typeAlias type="xxx.xxx.Student" alias="student"/><!--单个实体类别名注册-->
        <package name="xxx.xxx"/><!--批量注册别名 优先选择  别名是类名的驼峰命名法(规范)-->
    </typeAliases>

    <environments default="development">
    <!--配置数据库的环境变量(数据库连接配置) 
     default:使用下面的environment标签的id属性进行指定配置-->

        <environment id="development">
        <!--开发时在不同地点使用的数据库配置 
         id:就是提供给上面environments的default属性使用-->

            <transactionManager type="JDBC"/>
            <!--配置事务管理器: 
            type:指定事务管理的方式  
            JDBC:事务的控制交给程序员处理
            MANAGED:由容器(Spring)来管理事务 -->

            <dataSource type="POOLED">
            <!--配置数据源:  
            type:指定不同的配置方式   
            JNDI:java命名目录接口,在服务器端进行数据库连接池的管理
            POOLED:使用数据库连接池
            UNPOOLED:不使用数据库连接池-->

                <!--配置数据库连接的基本参数
                    private String driver;
                    private String url;
                    private String username;
                    private String password;
                -->
                <property name="driver" value="${jdbc.driverClassName}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>

        <!--在家的数据库配置-->
        <!--<environment id="home">-->
            <!--<transactionManager type=""></transactionManager>-->
            <!--<dataSource type=""></dataSource>-->
        <!--</environment>-->

        <!--上线后的数据库配置-->
        <!--<environment id="online">-->
            <!--<transactionManager type=""></transactionManager>-->
            <!--<dataSource type=""></dataSource>-->
        <!--</environment>-->
    </environments>

    <mappers><!--注册mapper.xml文件-->
      <!--<mapper resource="对应的实体类名Mapper.xml"/>-->
        <mapper class="xxx.xxx.对应的实体类名Mapper"/>
        <!--resource:从resources目录下找指定名称的文件注册
            url:使用绝对路径注册
            class:动态代理方式下的注册-->
    </mappers>

</configuration>

8.创建实体类,用来封装数据

以下用实体类Users示范

a.创建private(私有化)  封装类型(Integer)  成员变量(id)—>(必须对应数据库中的类型)等其他变量

public class Users {
    private Integer id;
    private String userName;
    private Date birthday;
    private String sex;
    private String address;

b.生成各种方法(需要注意的是,除了带参和无参的构造方法外,还需要一个不包含主键id的构造方法,方便后面sql的增删改查)

    public Users() {
    }

    public Users(Integer id, String userName, Date birthday, String sex, String address) {
        this.id = id;
        this.userName = userName;
        this.birthday = birthday;
        this.sex = sex;
        this.address = address;
    }

    public Users(String userName, Date birthday, String sex, String address) {
        this.userName = userName;
        this.birthday = birthday;
        this.sex = sex;
        this.address = address;
    }

..........其他生成方法略.........

9.创建对应的接口,通过接口中的方法来进行数据库的各种操作

public interface UsersMapper {
 //查询全部用户信息
 List<Users> getAll();
}

10.添加对应的实体类名Mapper.xml文件(用于表的增删改查的功能的实现)

使用select 需要先在SqlMapConfig.xml文件中配置<mappers>标签

SqlMapConfig.xml文件中注册mapper文件时,使用class=“接口的完全限定名称”

<mappers><!--注册mapper.xml文件-->  
        <mapper class="xxx.xxx.UsersMapper"/>       
</mappers>

<!--
注册mapper.xml文件
    <mappers>
        绝对路径注册
        <mapper url="/////"></mapper>
        非动态代理方式下的注册
        <mapper resource="UsersMapper.xml"></mapper>
        动态代理方式下的单个mapper.xml文件注册
        <mapper class="xxx.xxx.UsersMapper"></mapper>
        批量注册
        <package name="xxx.xxx"></package>
    </mappers> 
-->

配置 UsersMapper.xml文件

动态代理的实现规范:

UsersMapper.xml文件与UsersMapper.java的接口必须同一个目录下.

xml文件与java的接口的文件名必须一致,后缀不管.

xml文件中标签的id值与与java接口中方法的名称完全一致.

xml文件中标签的parameterType(参数类型)属性值与java的接口中方法的参数类型完全一致.

xml文件中标签的resultType(返回值类型)值与java的接口中方法的返回值类型完全一致.

xml文件中namespace属性必须是接口完全限定名称xxx.xxx.UsersMapper.

<?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="xxx.xxx.UsersMapper">
<!--mapper:是整个文件的大标签,用来开始和结束xml文件
属性:namespace:指定命名空间(相当于包名),用来区分不同mapper.xml文件中相同的id属性-->
<!--查询全部用户信息List<Users> getAll();-->
<select id="getAll" resultType="users" >
        select id,username,birthday,sex,address
        from users
    </select>
</mapper>

11.测试类:在test包下创建测试类

步骤:1.使用流读取核心配置文件。

步骤:2.创建SqlSessionFactory工厂对象

步骤:3.取出sqlSession的对象

步骤:4.取出动态代理的对象,完成接口中方法的调用,实则是调用xml文件中对应的标签的功能

步骤:5.关闭sqlSession

public class MyTest {
    SqlSession sqlSession;
    UsersMapper uMapper;
    
    // 有日期类型的可以用日期的格式化刷子
    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");

    @Before//这个注解表示是在所有的@Test方法执行前先执行的代码
    public void openSqlSession() throws IOException {
        //使用文件流读取核心配置文件SqlMapConfig.xml
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //创建SqlSessionFactory工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //取出sqlSession的对象
        sqlSession = factory.openSession();
        //取出动态代理的对象,完成接口中方法的调用,实则是调用xml文件中对应的标签的功能
        uMapper = sqlSession.getMapper(UsersMapper.class);
    }

    @After //这个注解表示是在所有的@Test方法执行后才执行的代码
    public void closeSqlSession(){
        //关闭sqlSession
        sqlSession.close();
    }

   @Test  //@Test注解表示这是个测试方法
   public void TestGetAll(){         //查询全部信息
   //取出动态代理的对象,完成接口中方法的调用,实则是调用xml文件中相的标签的功能
   //UsersMapper uMapper = sqlSession.getMapper(UsersMapper.class);
   //就是在调用接口的方法,mybatis框架已经为我们把功能代理出来了.
        List<Users> list = uMapper.getAll();
        list.forEach(users -> System.out.println(users));
    }
}

以下为拓展延伸知识 

12.特殊字符:#{}占位符,相当于传参大部分使用#{}传参,

#{}里如何写,看parameterType参数的类型

如果parameterType的类型是简单类型(8种基本(封装)+String),则#{}里随便写.

<select id="getById" parameterType="int" resultType="users">  ===>入参类型是简单类型
        select id,username,birthday,sex,address
        from users
        where id=#{zar}  ===>随便写
    </select>  

如果 parameterType的类型是实体类的类型,则#{}里只能是类中成员变量的名称,而且区分大小写.

<insert id="insert" parameterType="users" >  ===>入参是实体类
        insert into users (username, birthday, sex, address) 
        values(#{userName},#{birthday},#{sex},#{address})  ==>成员变量名称
    </insert>

13.特殊字符:${}字符串拼接字符串替换 字符串拼接,一般用于模糊查询中

如果parameterType的类型是简单类型,则${}里随便写

<select id="getByName" parameterType="string" resultType="users">  ===>入参是简单类型
        select id,username,birthday,sex,address
        from users
        where username like '%${zar}%'   ===>随便写
    </select> 

如果parameterType的类型是实体类的类型,则${}里只能是类中成员变量的名称.(现在已经少用) 

优化后的模糊查询(以后都要使用这种方式)

<select id="getByNameGood" parameterType="string" resultType="users">
        select id,username,birthday,sex,address
        from users
        where username like concat('%',#{name},'%')
    </select>

14. 返回主键值:在插入语句结束后, 返回自增的主键值到入参的users对象的id属性中.

 <insert id="insert" parameterType="users" >
        <selectKey  keyProperty="id" resultType="int" order="AFTER">
            select last_insert_id()
        </selectKey>
        insert into users (username, birthday, sex, address) 
        values(#{userName},#{birthday},#{sex},#{address})
 </insert>

  insert(插入)
  <selectKey>标签的参数详解:
    keyProperty: 返回的主键值所放入的users对象属性
    resultType:返回的主键的类型
    order:在插入语句执行前,还是执行后返回主键的值
    order=‘AFTER’:在insert语句执行后,即在执行insert语句后执行select last_insert_id(), 
    order=‘BEFORE’:则会获取前一条insert语句的自增主键的值。

    select last_insert_id():获取最后插入的主键值。
    

15.UUID :生成一个全球唯一随机字符串,由36个字母数字中划线组

public void testUUID(){
        UUID uuid = UUID.randomUUID();
        //可以按条件生成自己需要的
        //replace替换   substring截取位置之后的
        System.out.println(uuid.toString().replace("-","").substring(20));
    }

16.动态sql :可以定义代码片断,进行逻辑判断,进行循环处理(批量处理),使条件判断更为简单.

<sql>:用来定义代码片断,可以将所有的列名,或复杂的条件定义为代码片断,供使用时调用.

<include>:用来引用<sql>定义的代码片断. 

<!--定义代码片断-->
<sql id="allColumns">
   id,username,birthday,sex,address
</sql>
<!--查询全部用户信息List<Users> getAll();-->
<select id="getAll" resultType="users" >
    <!--select id,username,birthday,sex,address-->
        select <include refid="allColumns"/>
        from users
    </select>

<if>:进行条件判断

<where>:进行多条件拼接,在查询,删除,更新中使用.

按指定的条件进行多条件查询 getByCondition(按条件获取)
<select id="getByCondition" parameterType="users" resultType="users">
      select<include refid="allColumns"/>
      from users
     <where>
         <!-- 判断不为空或者不为空字符串,表示实体类中带有参数进来-->
         <if test="userName != null and userName != ''">
             <!--用户名模糊查询条件-->
             and username like concat('%',#{userName},'%')
         </if>
         <!-- 判断不为空,表示实体类中带有参数进来-->
         <if test="birthday != null">
           <!--生日等值查询条件-->
           and birthday = #{birthday}
         </if>
         <!-- 判断不为空或者不为空字符串,表示实体类中带有参数进来-->
         <if test="sex != null and sex != ''">
           <!--性别等值查询条件-->
           and sex = #{sex}
         </if>
         <!-- 判断不为空或者不为空字符串,表示实体类中带有参数进来-->
         <if test="address != null and address != ''">
           <!--地名模糊查询条件-->
           and address like concat('%',#{address},'%')
         </if>
     </where>
   </select>
接口中的方法
//按指定的条件进行多条件查询  
List<Users> getByCondition(Users users);
 @Test  
    //根据提供属性的条件模糊查询对应用户信息  最优
    public void testGetByCondition() throws ParseException {
        Users u = new Users();
        //u.setSex("1");
        // u.setAddress("市");
        //u.setUserName("小");
        // u.setBirthday(sf.parse("2002-01-19"));
        //无以上模糊条件就是查询全部信息
        List<Users> list = uMapper.getByCondition(u);
        list.forEach(users-> System.out.println(users));
    }

<set>:有选择的进行更新处理,至少更新一列.能够保证如果没有传值进来,则数据库中的数据保持不变. 

<!--有选择的更新 int updateBySet(Users users); -->
    <update id="updateBySet" parameterType="users">
        update users
        <set>
            <!-- 判断不为空或者不为空字符串,表示实体类中带有参数进来-->
            <if test="userName != null and userName != ''">
                <!--直接赋值-->
                username = #{userName},
            </if>
            <if test="birthday != null">
                birthday = #{birthday},
            </if>
            <if test="sex != null and sex != ''">
                sex = #{sex},
            </if>
            <if test="address != null and address != ''">
                address =#{address} ,
            </if>
        </set>
        where id = #{id}
    </update>
接口中的方法
//有选择的更新
int updateBySet(Users users);
@Test
//根据用户id更新用户部分信息,其他原始数据不变   最优
//有选择的进行更新处理,至少更新一列.能够保证如果没有传值进来,则数据库中的数据保持不变.否则sql语句不成立
    public void testUpdateSet() throws ParseException {
        Users u = new Users();
        u.setId(27);
        u.setUserName("星期一");
        u.setSex("1");
        u.setAddress("亦庄");
        int num = uMapper.updateBySet(u);
        System.out.println(num);
        //手工提交事务
        sqlSession.commit();
    }

<foreach>:用来进行循环遍历,完成循环条件查询,批量删除,批量增加,批量更新.

其中属性:
collection:用来指定入参的类型,如果是List集合,则为list,如果是Map集合,则为map,如果是数组,                      则为array.
item:每次循环遍历出来的值或对象
separator:多个值或对象或语句之间的分隔符
open:整个循环外面的前括号
close:整个循环外面的后括号

<!--查询多个指定id的用户信息List<Users> getByIds(Integer []arr); -->
    <select id="getByIds" resultType="users">
        select <include refid="allColumns"/>
        from users
        where id in
        <foreach collection="array" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </select>
<!--批量删除 int deleteBatch(Integer []arr);-->
    <delete id="deleteBatch" >
        delete from users
        where id in
        <foreach collection="array" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>
 <!--批量增加int insertBatch(List<Users> list);-->
    <insert id="insertBatch">
        insert into users(username, birthday, sex, address) values
        <foreach collection="list" item="u" separator="," >
            (#{u.userName},#{u.birthday},#{u.sex},#{u.address})
        </foreach>
    </insert>
接口中的方法
//查询多个指定id的用户信息
List<Users> getByIds(Integer []arr);
//批量删除
int deleteBatch(Integer []arr);
//批量增加
int insertBatch(List<Users> list);
@Test
    //同时通过id查询多个用户信息  最优
    public void testGetByIds(){
        Integer []array = {2,4,6};
        List<Users> list = uMapper.getByIds(array);
        list.forEach(users -> System.out.println(users));
    }
@Test
    //按id批量删除用户信息 最优
    public void testDeleteBatch(){
        Integer []array = {2,4,6};
        int num = uMapper.deleteBatch(array);
        sqlSession.commit();
        System.out.println(num);
    }
@Test
    //批量添加用户信息
    public void testInsertBatch() throws ParseException {
        Users u1 = new Users("aa",sf.parse("2002-05-05"),"2","朝阳a");
        Users u2 = new Users("bb",sf.parse("2002-05-05"),"2","朝阳b");
        Users u3 = new Users("cc",sf.parse("2002-05-05"),"2","朝阳c");
        Users u4 = new Users("dd",sf.parse("2002-05-05"),"2","朝阳d");
        List<Users> list = new ArrayList<>();
        list.add(u1);
        list.add(u2);
        list.add(u3);
        list.add(u4);
        int  num = uMapper.insertBatch(list);
        sqlSession.commit();
        System.out.println(num);
    }

17. 指定参数位置(方法1):如果入参是多个,可以通过指定参数位置进行传参. (实体类只能封装住成员变量的条件),但也有实体包含不住的条件,如某个成员变量要有区间范围内的判断,或者有两个值进行处理,则实体类包不住.例如:查询指定日期范围内的用户信息.

 <!--查询指定日期范围内的用户 List<Users> getByBirthday(Date begin, Date end);  -->
    <select id="getByBirthday" resultType="users">
        select <include refid="allColumns"/>
        from users
        where birthday between #{arg0} and #{arg1}
    </select>
//查询指定日期范围内的用户
List<Users> getByBirthday(Date begin, Date end);
@Test
//在指定日期范围内查询用户信息
public void testGetBirthday() throws ParseException {
        Date begin = sf.parse("1999-01-01");
        Date end = sf.parse("1999-12-31");
        List<Users> list = uMapper.getByBirthday(begin,end);
        list.forEach(users -> System.out.println(users));
}

入参是map(方法2重点掌握) : 如果入参超过一个以上,使用map封装查询条件,更有语义,查询条件更明确. 

 <!--入参是mapList<Users> getByMap(Map map);
    对应的id值就是getByMap
    #{birthdayBegin}   #{birthdayEnd}:都是map中的key-->
    <select id="getByMap" resultType="users" >
        select <include refid="allColumns"/>
        from users
        where birthday between #{birthdayBegin} and #{birthdayEnd}
    </select>
//入参是map
List<Users> getByMap(Map map);
@Test
//用map集合入参方式指定范围内查询用户信息
public void testGetByMap() throws ParseException {
        Date begin = sf.parse("1999-01-01");
        Date end = sf.parse("1999-12-31");
        Map map = new HashMap<>();
        //map.put("key",value);
        map.put("birthdayBegin",begin);
        map.put("birthdayEnd", end);
        List<Users> list = uMapper.getByMap(map);
        list.forEach(users -> System.out.println(users));
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌路学java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值