mybatis 的详细讲解(1)

本文详细介绍MyBatis框架的基础知识,包括配置、实体类设计、DAO层接口编写、XML映射文件配置以及使用注解的方式。涵盖增删改查操作的实现,深入解析SQL预编译原理,对比#{}

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

1、简介

mybatis是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql语句本身, 而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。**

mybatis通过xml 或注解的方式将要执行的各种statement配置起来,并通过java对象和statement 中 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并 返回。

采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc进行了封装,屏蔽了 jdbc api 底层访问细节,使我 们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。

2、mybatis入门配置文件实现

2.1 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>com.yuan</groupId>
    <artifactId>note_mybaties_01</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <!--        mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--        单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <!--            数据库-->
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <!--            日志-->
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
    </dependencies>

</project>

2.2 实体类

package com.yuan.doman;

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.3 编写dao层,持久层接口

package com.yuan.dao;

import com.yuan.doman.User;

import java.util.List;

/**
 * ,用户的持久层接口
 */
public interface UserDao {

    List<User> findAll();


}

2.4 编写映射文件 (mapper.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="com.yuan.dao.UserDao">
    <!--findAll方法-->
    <select id="findAll" resultType="com.yuan.doman.User">
        SELECT * FROM USER
    </select>
</mapper>

2.5 编写配置文件(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">
            <!--JDBC事务-->
            <transactionManager type="JDBC"></transactionManager>
            <!--POOLED连接池-->
            <dataSource type="POOLED">
            <!--四大参数-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///数据库名"/>
                <property name="username" value="数据库账户"/>
                <property name="password" value="数据库密码"/>
            </dataSource>
        </environment>
    </environments>

<mappers>
    <mapper resource="com/yuan/dao/UserDao.xml"/>
</mappers>
</configuration>

2.6 注意事项

第一个:创建UserDao.xml 和 UserDao.java时名称是为了和我们之前的知识保持一致。
在Mybatis中它把持久层的操作接口名称和映射文件也叫做:Mapper
所以:UserDao 和 UserMapper是一样的
第二个:在idea中创建目录的时候,它和包是不一样的
包在创建时:com.yuan.dao它是三级结构
目录在创建时:com.yuan.dao是一级目录
第三个:mybatis的映射配置文件位置必须和dao接口的包结构相同
第四个:映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名
第五个:映射配置文件的操作配置(select),id属性的取值必须是dao接口的方法名
第六个:当我们遵从了第三,四,五点之后,我们在开发中就无须再写dao的实现类。

2.7  测试

package com.yuan.test;

import com.yuan.dao.UserDao;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

public class UserDaoTest {
    InputStream is = null;
    SqlSessionFactory factory = null;
    SqlSession session = null;

    @Before
    public void init() throws IOException {
        //读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //创建会话工厂
        factory = new SqlSessionFactoryBuilder().build(is);
        //生产SQLSession对象
        session = factory.openSession();
    }
    
    @After
    public void close() throws IOException {
        session.commit();
        session.close();
        is.close();
    }

    @Test
    public void findAllTest(){
        UserDao userDao = session.getMapper(UserDao.class);
        System.out.println(userDao.findAll());
    }

}

3、使用注解的方式

3.1 pom.xml  和2.1 相同

3.2 实体类 和2.2 相同

3.3 持久层接口

package com.yuan.dao;

import com.yuan.doman.User;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * 用户的持久层接口
 */
public interface UserDao {

    @Select("SELECT * FROM USER")
    List<User> findAll();


}

3.4 编写配置文件

<mappers>
    <mapper class="com.yuan.dao.UserDao"/>
</mappers>

3.5 测试和2.7相同

4、小结

无论是注解方式,还是xml方式,那个简单、好维护容易实现功能,就使用

5、程序的增删改查

5.1、持久层(dao层)实现

package com.yuan.dao;

import com.yuan.doman.User;

import java.util.List;

/**
 * 用户的持久层接口
 */
public interface UserDao {

    /**
     * 全查User
     *
     * @return
     */
    List<User> findAll();

    /**
     * 查询UserId
     *
     * @param uid
     */
    User findById(Integer uid);

    /**
     * 查询UserName
     *
     * @param username
     */
    List<User> findLikeName(String username);

    /**
     * 查询User总数
     *
     * @return int
     */
    Integer findTotalId();

    /**
     * 新增User
     *
     * @param user
     */
    void save(User user);

    /**
     * 修改User
     *
     * @param user
     */
    void update(User user);

    /**
     * 删除User
     *
     * @param uid
     */
    void delete(Integer uid);


}

5.2、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="com.yuan.dao.UserDao">

    <!--查询全部User-->
    <select id="findAll" resultType="com.yuan.doman.User">
        SELECT * FROM USER
    </select>

    <!--查询单个User-->
    <select id="findById" resultType="com.yuan.doman.User" parameterType="int">

        SELECT * FROM USER WHERE ID = #{id}
    </select>

    <!--Like查询UserName-->
    <select id="findLikeName" resultType="com.yuan.doman.User" parameterType="string">
        SELECT * FROM USER WHERE USERNAME LIKE #{uname};
    </select>

    <!--查询User总数-->
    <select id="findTotalId" resultType="int">
        SELECT count(*) FROM USER
    </select>

    <!--新增User-->
    <insert id="save" parameterType="com.yuan.doman.User">
        <!--拿到返回的ID-->
        <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
            SELECT Last_INSERT_ID();
        </selectKey>
                INSERT INTO USER(username,birthday,sex, address) VALUE (#{username},#{birthday},#{sex},#{address});
    </insert>

<!--    更新User根据ID-->
    <update id="update" parameterType="com.yuan.doman.User">
        UPDATE USER SET USERNAME = #{username} WHERE ID = #{id}
    </update>

    <!--删除User根据ID-->
    <update id="delete" parameterType="Integer">
        delete FROM user WHERE ID = #{uid}
    </update>
    
</mapper>

5.3 单元测试

package com.yuan.test;

import com.yuan.dao.UserDao;
import com.yuan.doman.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

public class UserDaoTest {
    InputStream is = null;
    SqlSessionFactory factory = null;
    SqlSession session = null;

    /**
     * 在Test
     * @throws IOException
     */
    @Before
    public void init() throws IOException {
        //读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //创建会话工厂
        factory = new SqlSessionFactoryBuilder().build(is);
        //生产SQLSession对象
        session = factory.openSession();
    }
    
    @After
    public void close() throws IOException {
        session.commit();
        session.close();
        is.close();
    }

    @Test
    public void findAllTest(){
        UserDao userDao = session.getMapper(UserDao.class);
        System.out.println(userDao.findAll());
    }

    @Test
    public void testSave() {
        UserDao userDao = session.getMapper(UserDao.class);
        User user = new User();
        user.setUsername("GiaoWin");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setAddress("张家口");

        System.out.println("保存前 = " + user);
        userDao.save(user);
        System.out.println("保存后 = " + user);
    }


    @Test
    public void testUpdate() {
        UserDao userDao = session.getMapper(UserDao.class);
        User user = new User();
        user.setUsername("AKUMA");
        user.setId(49);
        userDao.update(user);
    }
    @Test
    public void testDelete() {
        UserDao userDao = session.getMapper(UserDao.class);
        userDao.delete(49);
    }

    @Test
    public void testfindById() {
        UserDao userDao = session.getMapper(UserDao.class);
        System.out.println(userDao.findById(46));
    }

    @Test
    public void testfindAll() {
        UserDao userDao = session.getMapper(UserDao.class);
        System.out.println(userDao.findAll());
    }

    @Test
    public void testfindLikeName() {
        UserDao userDao = session.getMapper(UserDao.class);
        userDao.findLikeName("%王%");
    }

    @Test
    public void testfindTotalUser() {
        UserDao userDao = session.getMapper(UserDao.class);
        System.out.println("+++++++++++++++++++++++"+userDao.findTotalId()+"++++++++++++++++++++++++");
    }

}

6、小结

#{}h和${}有什么区别

#{}:占位符

案例:

String username="lisi";
select * from User where username = #{username}


--》
select * from User where order_no = 'lisi'

${}则仅仅是一个纯粹的字符串替换 (会受到SQL注入攻击)

select * from User where username= '${username}' 
-->

select * from User where username = 'lisi' 

一般${} 用于数字类型的参数、#{} 用于字符串类型的参数,尽量用#{}

注意:

1.使用#{},相同的预编译sql可以重复利用,性能比${}高;

​ 2. ${}在预编译之前已经被变量替换了,会存在sql注入问题。

例如

select * from ${tableName} where username= #{username}

如果从客户端传入的tableName = “order;delete order; – “,那么sql动态解析之后,预编译之前的sql将变为:

select * from order;delete order; -- where username= #{username}

获得添加时返回的自增ID

    <!--拿到返回的ID-->
    <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
        SELECT Last_INSERT_ID();
    </selectKey>

多个查询条件组成一个对象作为参数怎么解决?

用一个包装类给他们包装一下,然后通过NGOL表达式逐一拿出

7、sql预编译

定义:sql 预编译指的是数据库驱动在发送 sql 语句和参数给 DBMS 之前对 sql 语句进行编译,这样 DBMS 执行 sql 时,就不需要重新编译。

为什么需要预编译
JDBC 中使用对象 PreparedStatement 来抽象预编译语句,使用预编译

预编译阶段可以优化 sql 的执行。
预编译之后的 sql 多数情况下可以直接执行,DBMS 不需要再次编译,越复杂的sql,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。
预编译语句对象可以重复利用。
把一个 sql 预编译后产生的 PreparedStatement 对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的 PreparedState 对象。
END….

DBMS:数据库管理系统(Database Management System,DBMS)是一种操纵和管理数据库的大型软件,是用于建立、使用和维护数据库。它对数据库进行统一的管理控制,以保证数据库的安全性和完整性。用户通过dbms访问数据库中的数据,数据库管理员也通过dbms进行数据库的维护工作。它提供多种功能,可使多个应用程序和用户用不同的方法在同时或不同时刻去建立,修改和询问数据库。它使用户能方便地定义和操纵数据,维护数据的安全性和完整性,以及进行多用户下的并发控制和恢复数据库。

功能:

1.数据定义:DBMS提供数据定义语言DDL(Data Definition Language),供用户定义数据库的三级模式结构、两级映像以及完整性约束和保密限制等约束。DDL主要用于建立、修改数据库的库结构。DDL所描述的库结构仅仅给出了数据库的框架,数据库的框架信息被存放在数据字典(Data Dictionary)中。

2.数据操作:DBMS提供数据操作语言DML(Data Manipulation Language),供用户实现对数据的追加、删除、更新、查询等操作。

3.数据库的运行管理:数据库的运行管理功能是DBMS的运行控制、管理功能,包括多用户环境下的并发控制、安全性检查和存取限制控制、完整性检查和执行、运行日志的组织管理、事务的管理和自动恢复,即保证事务的原子性。这些功能保证了数据库系统的正常运行。

4.数据组织、存储与管理:DBMS要分类组织、存储和管理各种数据,包括数据字典、用户数据、存取路径等,需确定以何种文件结构和存取方式在存储级上组织这些数据,如何实现数据之间的联系。数据组织和存储的基本目标是提高存储空间利用率,选择合适的存取方法提高存取效率。

5.数据库的保护:数据库中的数据是信息社会的战略资源,所以数据的保护至关重要。DBMS对数据库的保护通过4个方面来实现:数据库的恢复、数据库的并发控制、数据库的完整性控制、数据库安全性控制。DBMS的其他保护功能还有系统缓冲区的管理以及数据存储的某些自适应调节机制等。

6.数据库的维护:这一部分包括数据库的数据载入、转换、转储、数据库的重组合重构以及性能监控等功能,这些功能分别由各个使用程序来完成。

7.通信:DBMS具有与操作系统的联机处理、分时系统及远程作业输入的相关接口,负责处理数据的传送。对网络环境下的数据库系统,还应该包括DBMS与网络中其他软件系统的通信功能以及数据库之间的互操作功能。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值