mybatis

SSM框架

一、mybatis框架

1.介绍

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。

半自动的ORM(Object/ Relational Mapping,即对象关系映射)框架。ORM框架常用有两个:Hibernate和MyBatis框架。

2.ORM的介绍

ORM(对象关系映射):以对象的方式操作数据库

比如定义一个对象和数据库表字段一致,那么就可以直接操作这个对象,就可以自动生成SQL语句.
 如:userDao.insert(user对象) ,无需书写SQL语句就可以实现数据的插入

ORM的核心映射机制

​ 数据表 <-对应-> java对象

​ 数据表字段 <-对应-> java对象中的属性

1)全自动映射

当用户执行代码userDao.insert(user对象),映射框架解析成insert into 表名(字段1,字段2,字段3...) values(属性值1,属性值2,属性值3.....)
------------------------------------------
用户查询操作:List<User> userList = userDao.selectList(user对象);

select * from 表名 where xxxx=xxxx and xxx= xxx
结果集自动的封装成对象

自动实现对象的封装

自动生成SQL语句

2)半自动ORM的mybatis

可以实现对象的自动封装,但是不能自动生成SQL语句.

3.mybatis的入门代码编辑(Maven项目下)

总体的项目结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XDR0Aujp-1659013934685)(D:\Typora\bin\document\img\1658917077363.png)]

1.导入jar包
<dependencies>

        <!--导入MySQL的驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>

        <!--导入MyBatis的jar包-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
    
        <!--log4j-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    
</dependencies>

2.数据库表和实体对象

必须保证数据表和对象一一映射,表中字段和对象属性一一映射

3.编写xxxMapper接口

(和Dao接口一类,只是命名格式不同,用来定义操作数据库的方法)

4.编写xxxMapper对应的映射文件xxxMapper.xml

该xml文件只是替代了实现类,在该xml中书写SQL

<?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="xxxMapper的全限定名(全路径)">
    <select id="Mapper接口中对应的方法名" resultType="要封装实体的全限定名">
       SQL语句
    </select>
    <inser  id=""></inser>
    <update id=""></update>
    <delete id=""></delete>
</mapper>
----------------------------------------------------------------------------------
<!--
    namespace:
        1.与mapper的接口文件一一映射  接口的包路径
        2.路径内容必须唯一,如果重复mybatis一定报错提示.

-->
<mapper namespace="com.atguigu.mybatis.mapper.UserMapper">

    <!--
        1.根据业务规范,挑选sql标签
            1.1 查询:  select
            1.2 新增:  insert
            1.3 修改:  update
            1.4 删除:  delete
        2.id属性必须与接口中的方法名称一一对应.
        3.resultType 只有查询操作有该属性. 内容:实体对象的包路径写法
    -->
    <select id="getAllUser" resultType="com.atguigu.mybatis.pojo.User">
        select * from demo_user
    </select>

</mapper>
5.核心配置文件mybatis-config.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>
    <!--设置连接数据库的环境
	数据库可以有多个环境,但一次只能用一个,default="xxx"就是对应的环境,绑定的是对应的id
	-->
    <environments default="development">
        <environment id="development">
            <!--事务管理,为默认的jdbc-->
           <transactionManager type="JDBC"/>
           <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/atweb?serverTimezone=UTC&amp;rewriteBatchedStatements=true&amp;characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--引入映射文件-->
    <mappers>
    <mapper resource="mappers/UserMapper.xml"/>
</mappers>
</configuration>
6.单元测试

步骤:

1.读取配置文件

InputStream is = Resources.getResourceAsStream("mybatis-config.xml");		

2.通过SqlSessionFactoryBuilder 创建SqlSessionFactory

SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(resource);

3.通过SqlSessionFactory获得SqlSession

SqlSession sqlSession=sqlSessionFactory.openSession();

4.获取Mapper接口

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

5.调用mapper接口中的方法

List<User> userList = userMapper.getAllUser();


或者使用[了解]
  List<User> list = sqlSession.selectList("com.atguigu.mybatis.mapper.UserMapper.getAllUser");
  

getAllUser()是mapper接口中的方法,mybatis会根据映射关系,执行映射文件中的id为getAllUser的sql标签
@Test
    public void findCount() throws IOException {
        
InputStream resource = Resources.getResourceAsStream("mybatis-config.xml");
        
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(resource);
        
SqlSession sqlSession=sqlSessionFactory.openSession();
        
UserMapper mapper=sqlSession.getMapper(UserMapper.class);
        
	int count = mapper.findCount();
        
    System.out.println(count);
    }

userMapper.xxx调用的是接口中的方法,mybatis根据映射关系,执行映射文件中id为xxx的sql标签.

注意:在接收返回数据时,如果根据主键查询必返回一个对象,用对象接收.如果不确定,则使用list<实体对象>进行接收

7.Sqlsession的简化操作

通过@Before标签 简化sqlSession的赋值操作

 private  SqlSession sqlSession;

	@Before
	public void init() throws IOException {
        //读取mybatis-config.xml核心配置文件
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        //创建mybatis中操作数据库的会话对象SqlSession
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new  SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
        sqlSession = sqlSessionFactory.openSession();
    }
    
@Test
    public void findCount() throws IOException {
        UserMapper mapper=sqlSession.getMapper(UserMapper.class);
        
        int count = mapper.findCount();
        System.out.println(count);
    }   

4.mybatis常见错误及解决办法

报错说明1:

org.apache.ibatis.binding.BindingException: Type interface com.jt.mapper.UserMapper is not known to the MapperRegistry.

解决方案1:
1.检查namespace命名是否与接口一致

​ 2. 检查Mybatis核心配置文件是否加载映射文件.

报错说明2:

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.jt.mapper.UserMapper.findAll

解决方案2:
检查xml映射文件中的ID是否与接口方法一致.

报错说明3:

The error may exist in mybatis/mappers/UserMapper2.xml

解决方案3:
检查mybatis核心文件加载mapper映射文件的路径是否正确.

5.log4j日志的使用

在pom.xml中引入jar包,在resources下放置log4j.xml

需求:在使用mybatis时,执行时不会打印SQL语句,为了检验sql语句的执行正确性,使用log4j用来在执行时打印SQL

位置:在resources下

日志级别

日志级别从左到右打印的内容越来越详细
FATAL(致命) > ERROR(错误) > WARN(警告) > INFO(信息) > DEBUG(调试)

6.数据库的动态配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dkwod1Fq-1659013934695)(D:\Typora\bin\document\img\1658922186039.png)]

#key=value
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/atweb?serverTimezone=UTC&rewriteBatchedStatements=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

serverTimezone=UTC 时区:标准时区

rewriteBatchedStatements=true 批处理,提高批量处理SQL语句的执行效率

characterEncoding=utf-8 编码格式utf-8

	 <dataSource type="POOLED">
       <property name="driver" value="${jdbc.driver}"/>
       <property name="url" value="${jdbc.url}"/>
       <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
     </dataSource>

7.mybatis核心配置文件mybatis-config.xml

mybatis-config.xml中,所有的配置都是在标签内,这些标签在使用时,要遵循相应的顺序

​ properties,settings,typeAliases,

​ typeHandlers,objectFactory,

​ objectWrapperFactory,reflectorFactory,plugins,

​ environments,databaseIdProvider,mappers.

从上到下的顺序

8.mybatis中typeAliases(别名)的使用

需求:在xxxMapper.xml中,resultType=“返回值类型”,书写的太复杂,可以使用别名定义.

<select id="getAllUser" resultType="com.atguigu.mybatis.pojo.User">
</select>

此处的User就是一个别名,代表com.atguigu.mybatis.pojo.User
通过下面的别名定义实现
    1|2|4 在mybatis-config.xml中配置
   	3在实体类上
-----------------------------------

<select id="getAllUser" resultType="User">
</select>
               

1)通过标签定义

 <!--定义别名-->
    <typeAliases>
        <!-- 通过alias指定对象的别名 -->
        <typeAlias type="com.atguigu.mybatis.pojo.User" alias="User"/>
    </typeAliases>

2)简化alias

 <!--定义别名-->
    <typeAliases>
        <!--如果没有alias属性 则默认使用类名 别名不区分大小写-->
        <typeAlias type="com.atguigu.mybatis.pojo.User"/>
    </typeAliases>

3)注解写法

@Alias("User")
public class User implements Serializable {...}

4)定义别名

<typeAliases>
  <package name="com.atguigu.mybatis.pojo"/>
</typeAliases>

9.映射文件中的元素

映射文件是 MyBatis框架中十分重要的文件,在映射文件中,元素是映射文件的根元素,其他元素都是它的子元素

1、< select >

用于映射查询语句,它用于从数据库中读取出数据,并组装数据给业务开发人员。

<select id="findUserById" parameterType="Integer" resultType="com.ssm.po.User">
    
select * from t_user where id=#{id}
    
</select>

上述语句中的唯一标识为findUserById,它接收一个 Integer类型的参数,并返回一个User类型的对象。

2、 < insert >元素< update > < delete >

用于映射插入语句,在执行完元素中定义的SQL语句后,会返回一个表示插入记录数的整数。

<!--//添加用户  -->
<insert id="addUser" parameterType="com.ssm.po.User">
insert into t_user(username,jobs,phone) values(#{username},#{jobs},#{phone})
</insert>
3、 < sql >元素

元素的作用就是定义可重用的SQL代码片段,然后在其他语句中引用这一代码片段。

定义重复SQL:

< sql id=“user_column”>
id,name,age,sex
< /sql>

引入标签:

< include refid=“user_column”/>

    <sql id="user_column">
        id,name,age,sex
    </sql>
    <select id="getAllUser" resultType="User">
        select  <include refid="user_column"/>    from demo_user
    </select>

10.参数传递

#{}和${}的用法和区别

#号它是有预编译的效果(相当于 PraperStatement ),参数使用?进行占位,并且默认为参数添加引号

$号是直接将字符串进行拼接,没有预编译的效果,使用时需要手动添加引号

原则: 能用#号 不要使用$符,除非以字段名称为参数时使用.

1.单值参数传递

mybatis单值数据传递时和参数的名称无关. 通过参数下标的方式获取的.

建议: 虽然和名称无关,但是一般的参数 见名知意.

<select id="findUserByName" resultType="User">
        select * from demo_user where name='${abc}'
</select>
2.多值参数传递
1)通过数组进行取值

Mybatis进行多值参数传递时,内部使用数组的结构,所以需要通过下标的方式取值.

例如: Available parameters are [arg0, arg1, param1, param2]

<select id="findUserByAS" resultType="User">
        <!--select * from demo_user where age=#{arg0} and sex=#{arg1}-->
        select * from demo_user where age=#{param1} and sex=#{param2}
    </select>

弊端: 用户传递的数据是有参数名称的, 如果大量使用下标的方式,则会导致sql业务理解不方便

2)Map集合

说明: 如果用户需要进行多值参数传递,则可以使用map集合进行封装.

编辑测试类:

 /**
     * 要求  按照age和性别查询数据
     */
    @Test
    public void test04(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int age = 3030;
        String sex = "男";
        Map<String,Object> map = new HashMap<>();
        map.put("age",age);
        map.put("sex",sex);
        List<User> list = mapper.findUserByMap(map);
        list.forEach(System.out::println);
    }

xml映射文件

<!--
        如果参数是Map集合,则#{map中的key}
    -->
    <select id="findUserByMap" resultType="User">
        select * from demo_user where age=#{age} and sex=#{sex}
    </select>
3)注解封装

说明: 使用@Param注解封装参数

注解封装在底层还是运用了map集合进行的处理

  1. 编辑测试类
/**
     * mybatis 多值查询,注解写法
     */
    @Test
    public void test05(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int age = 2851;
        String sex= "女";
        List<User> list = mapper.findUserByAnno(age,sex);
        list.forEach(System.out::println);
    }
  1. 编辑接口
 /**
     * 原理说明:
     *      Mybatis中使用多值参数传递时,核心用法就是将参数封装为Map集合.
     *      key: @Param("age") 中的值 age
     *      value: int age 的值
     *      其中的key不能重复. 如果一旦传递map集合则取值时必须使用#{key}
     * @param age
     * @param sex
     * @return
     */
    List<User> findUserByAnno(@Param("age") int age,@Param("sex") String sex);
  1. 编辑映射文件
 <select id="findUserByAnno" resultType="User">
        select * from demo_user where age=#{age} and sex=#{sex}
</select>
4)实体对象封装

需求: 根据实体对象中的数据查询数据.

  1. 编辑测试类
/**
     * 实体对象查询
     * 规则说明: 如果参数较多,则可以使用对象的方式封装.
     */
    @Test
    public void test06(){
        User user = new User();
        user.setName("铁扇公主");
        user.setAge(1273);
        user.setSex("女");

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> list = mapper.findUser(user);
        list.forEach(System.out::println);
    }
  1. 编辑Mapper接口
List<User> findUser(User user);
  1. 编辑Mapper.xml映射文件
<!--

        如果参数是单值,并且使用对象的方式包装.则取值时和名称无关,和属性有关
        前提条件: 对象中必须有get/set方法..
    -->
    <select id="findUser" resultType="User">
        select * from demo_user where name=#{name} and age=#{age} and sex=#{sex}
    </select>

重要知识理解:

Mybatis中的参数其实只能允许单值传递(数据可以被封装为单值)

在使用mybatis进行数据库的增删改查时,凡是数据发生改变[如增删改]的都需要加上sqlSession.commit();sqlSession.close()用于事务的提交.

11.转义字符

 <!--特殊转义字符
        > &gt;
        < &lt;
        & &amp;
        万能转义标签   <![CDATA[ 需要转义的内容 ]]>
    -->
select * from demo_user where age &gt;=#{starAge} and age &lt;= #{endAge}
------------------------------------------
 select * from demo_user where age >=? and age <= ? 

lombok的注解说明:

@Accessors(chain = true)

@Accessors 注解用来配置lombok如何产生和显示get和set的方法,@Accessors(chain = true)加上参数以后就可以开启链式编程.

传统set方法赋值(臃肿、占空间)

 Person person = new Person();
 person.setName("wang");
 person.setSex("男");
 person.setEmail("123@qq.com");
 person.setDate(new Date());
 person.setAddr("山东");

加上@Accessors(chain = true)

 Person person = new Person();
 person.setName("wang").setSex("男").setEmail("123@qq.com").setDate(new Date()).setAddr("山东");

11.ResultMap

当表中的字段与POJO中的属性不能完全匹配时, 则需要使用resultMap映射.

ResultMap解决在数据库中的字段名和实体类中属性名不一致,无法自动映射的问题(数据库:user_id 属性:userId)

案例描述

​ 1)实体类:

@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class Users implements Serializable {
    private Integer id;
    private String tName;
    private Integer tAge;
    private String sex;
}

​ 2)UsersMapper接口

public interface UserMappers {

    List<Users> selectUser();
}

​ 3)UsersMapper.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.ssm.mybatis.mapper.UserMappers">
    <!--
        解决的数据库字段和实体类属性因为不同而无法自动映射的问题
		autoMapping: 如果字段与名称相同,是否自动映射,  默认值为true 旧版本为false
        id: resultMap的主键标识 可以复用
		result:除id外使用
			column="数据库字段"
			property="对应的属性"
    -->
    <resultMap id="userIds" type="users" autoMapping="false">
        <result column="t_name" property="tName"/>
        <result column="t_age" property="tAge" />
    </resultMap>
    <select id="selectUser" resultType="users">
        select * from demo_user1
    </select>
</mapper>

4)mybatis-config.xml

在properties标签下生效,要依照执行顺序
    
<settings>
        <!--是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    
    
........................................
<mappers>
  <mapper resource="mappers/UserMappers.xml"/>
</mappers>

5)测试类

@Test
    public void selectUser() throws IOException {
        InputStream rs = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(rs);
        SqlSession sqlSession=sqlSessionFactory.openSession();
        UserMappers mapper=sqlSession.getMapper(UserMappers.class);
        List<Users> userList=mapper.selectUser();
        System.out.println(userList);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

点份炸鸡778

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

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

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

打赏作者

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

抵扣说明:

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

余额充值