Mybatis

Mybatis

构建mybatis项目的步骤:

1.

使用idea新建一个maven工程

2.

pom.xml文件中中导入相应的依赖,一般基础的依赖包括如下几个

<!--导入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>

<!--导入junit依赖-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.1</version>
    <scope>test</scope>
</dependency>

mybatis核心配置文件(resources下,springBoot中直接导入依赖坐标即可,配置好数据库连接,不用配置mybatis-config.xml):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>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--下面四个property是数据库的连接信息-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db1?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="208713"/>
            </dataSource>
        </environment>
    </environments>
    <!--mappers指定sql映射文件的路径-->
    <mappers>
        <!--加载sql的映射文件-->
        <!--<mapper resource="MybatisDemo/Mapper/BrandMapper.xml"/>-->
        <!--注释掉上面的一句,改为下面一句,使用包扫描的方式,只要是Mapper文件夹下中的mapper接口,都能扫描出来,但命名规则需要一致-->
        <package name="MybatisDemo.Mapper"/>
    </mappers>
</configuration>

***还有一个logback,这个根据自己的需要添加:

<!--添加slf4j日志api-->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.2</version>
</dependency>

<!--添加logback-classic依赖-->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.11</version>
</dependency>

<!--添加logback-core依赖-->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>1.2.11</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.8</version>
</dependency>

logback日志还要在resources中新建一个logback.xml配置文件:

logback.xml

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <!--CONSOLE:表示当前的日志信息是可以输出到控制台的-->
    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type
        ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
        <encoder>
            <pattern>[%level] %blue(%d{HH:mm:ss.SSS}) %cyan([%thread]) %boldGreen(%logger{15}) - %msg %n</pattern>
        </encoder>
    </appender>

    <logger>
        <appender-ref ref="Console"/>
    </logger>
</configuration>

3.

在src/main/java文件夹下建立pojo,mapper等文件夹,当然,也可以先建立一个文件夹,将pojo,mapper等文件夹放到里面,由于resources和java目录都是在main目录下的,maven中默认两者是同一个文件夹,因此,resources中的.xml文件寻找相应的类时,如果这个类是直接在java文件夹下,直接写类名即可,不需要再逐级查找:

例如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zR8915nT-1649061081643)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20220330091934824.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZyPpUkrU-1649061081644)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20220330091956360.png)]

在maven1的项目中,maven核心配置文件mybatis-config.xml中的标签字段中通过包扫描机制查找mapper接口,直接写成即可,不用写成java.MybatisDemo.Mapper。

注意:采用这种包扫描机制查找mapper接口时,要保证pojo类中的属性和数据库中属性的名称命名方式相同,常见的一个错误就是,数据库中用brand_name命名,而pojo类中的属性用brandName命名,这样会导致mybatis因为查找到的名称不对应,无法完成自动封装(解决方法下面会有详解)

4.

编写mapper文件夹中各个接口对应的映射文件(xxxMapper.xml)

下面以BrandMapper.xml为例

pojo中实现Brand类:

public class Brand {
    private int id;
    private String brand_name;//这里采用的命名方式和数据库表中的命名方式相同
    private String company_name;
    private int orderd;
    private String description;
    private int status;
    ...
}

Mapper中的BrandMapper接口

public interface BrandMapper {
    /*查询所有*/
    List<Brand> selectAll();
    Brand selectById(int id);
}

注:在mybatis的映射机制中,sql标签(<select\insert…>)中的resultType对应的实体类的属性名称和数据类型,只有与数据库中的属性名对应上时,才会自动封装,否则不会映射成功,当属性名不一致时,要使用resultmap手动编写代码指明映射

第一种方式(最初)

BrandMapper.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="test">
    <select id="selectAll" resultType="MybatisDemo.pojo.Brand">
        select * from tb_brand;
    </select>
</mapper>

对于其他sql语句标签,例如,等

<delete id="deleteByUserId" parameterType="java.lang.Integer">
    delete from introduction.resumes where user_id = #{user_id};
</delete>
<insert id="addResume" parameterType="com.xdhyy.resume.pojo.Resume">
        insert into introduction.resumes(resume_id,resume_name,age,work_experience,education_experience,telephone_number,email_address,intention,detail,user_id)
        values(#{resume_id},#{resume_name},#{age},#{work_experience},#{education_experience},#{telephone_number},#{email_address},#{intention},#{detail},#{user_id});
    </insert>

MybatisDemo中的测试:

public class MybatisDemo {
    public static void main(String[] args) throws Exception{
        //1.加载Mybatis的核心配置文件,获取SqlSessionFactory
        //String resource = "resources/mybatis-config.xml";
        //java文件夹下的类会主动到resources下寻找相应的.xml文件,直接写mybatis-config.xml即可,不必写resources/mybatis-config.xml
        String resource="mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession对象,用来执行sql
        SqlSession sqlSession=sqlSessionFactory.openSession();

        //执行sql语句
        //下面的语句是对应的没有使用包扫描方式的方法,有些语句已经在配置文件中注释掉了
        List<User> users=sqlSession.selectList("test.selectAll");
        System.out.println(users);

        //释放资源
        sqlSession.close();
    }
}

第二种方式(使用Mapper代理

在使用Mapper代理时,要注意数据库属性与pojo类种属性命名的方式是否一致,否则Mybatis无法完成自动封装。

Mapper代理中为了保证BrandMapper.xml文件能映射到Mapper中的接口,要在resources中建立一个与xxxMapper接口所在文件夹相同的文件夹,存储xxxMapper.xml文件,这里在resources中新建MybatisDemo.Mapper文件夹时,在新建时,要写成MybatisDemo/Mapper,不要写成Mybatis.Mapper

<?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">
<!--注意!注意!:这里在resources中新建MybatisDemo.Mapper文件夹时,在新建时,要写成MybatisDemo/Mapper,不要写成Mybatis.Mapper-->
<mapper namespace="MybatisDemo.Mapper.BrandMapper"> 
    <!--使用mapper代理时,此时的id='selectAll'表示接口UserMapper中
    必有一个名为selectAll的方法,返回值的类型为User(由MybatisDemo.pojo.User得知)
    这与不适用mapper代理还是有区别的,不使用mapper代理时,使用sqlSession.selectList("test.selectAll")
    test.selectAll由namespace+id组成-->
    <select id="selectAll" resultType="MybatisDemo.pojo.Brand">
        select * from tb_brand;
    </select>
    <!--这里的参数parameterType可以省略-->
    <select id="selectById" parameterType="int" resultType="MybatisDemo.pojo.Brand">
        select * from tb_brand where id=#{id};
    </select>
    <!--这里是select * ,对实体类中的属性的命名没有要求,当不是select *的时候,才会有要求(数据库中的属性名和实体类中的属性名一致,否则不能自动封装)
    例如:
    <select id="selectOne" resultType="Mybatisdemo.pojo.Brand">
        select brand_name from tb_brand as brandName where id=1;<!--将数据库中的属性名brand_name设为实体类中的对应名brandName-->
    </select>
    -->
</mapper>
<?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="MybatisDemo.Mapper.BrandMapper"> 
    <select id="selectAll" resultType="MybatisDemo.pojo.Brand">
        select * from tb_brand;
    </select>
    <select id="selectById" parameterType="int" resultType="MybatisDemo.pojo.Brand">
        select * from tb_brand where id=#{id};
    </select>
</mapper>

MybatisDemo中测试:

public class MybatisDemo2 {
    public static void main(String[] args) throws Exception{
        //mybatis的mapper代理模式
        //1.加载mybatis的核心配置文案,获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2.获取SqlSession对象,用于执行sql
        SqlSession sqlSession=sqlSessionFactory.openSession();

        //3.1获得UserMapper接口的代理对象,这个过程是由mybatis内部实现的
        /*这种方式的好处是,当Mapper文件夹中有多个mapper接口时,并且mapper接口中有多个方法时
        * 比不适用mapper代理要轻松的多*/
        //从下面这一句开始,与MybatisDemo中的代码有所不同。
        //使用SqlSession中的getMapper(UserMapper.class)获得接口的代理对象
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        BrandMapper brandMapper=sqlSession.getMapper(BrandMapper.class);

        List<User> users=userMapper.selectAll();//这个selectAll()返回的类型是User类型
        List<Brand> brands=brandMapper.selectAll();
        System.out.println(users);
        System.out.println(brands);
        sqlSession.close();
    }
}

使用Mapper代理后,还可以对XXXMapper.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="MybatisDemo.Mapper.BrandMapper">
     <!--可已将sql语句的公共部分提取出来,如下,将brand_name as brandName提取出来-->
    <sql id="brand_column">brand_name as brandName</sql>
    <!--这个时候的select标签中的依旧是属性resultType,在使用resultMap时要改为resultMap-->
    <select id="selectOne" resultType="Mybatisdemo.pojo.Brand">
        select 
            <include refid="brand_column"/>
        from tb_brand;
    </select>
</mapper>

改进二 resultmap(至于是否使用到这种改进,要看数据库中的属性名和自己写的dao层的实体类的属性名是否相同,如果相同,则不用使用resultmap):

使用restltmap,以后会经常用到:

<?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">
        <!--注意!注意!:这里在resources中新建MybatisDemo.Mapper文件夹时,在新建时,要写成MybatisDemo/Mapper,不要写成Mybatis.Mapper-->
<mapper namespace="MybatisDemo.Mapper.BrandMapper">
<resultMap id="brandResultMap" type="Brand">
    <!--
    id:完成主键字段的映射
       column:表的列名
       property:实体类的属性名
    result:完成一般字段的映射
        column:表的别名
        property:实体类的属性名
    -->
    <!--将数据库中的属性brand_name转为实体类中的brandName,这样对应上了就能进行自动封装了-->
    <result column="brand_name" property="brandName"/>
    <result column="company_name" property="companyName"/>
</resultMap>
<!--调用resultMap之后,select标签中的属性resultType改为resultMap-->
<select id="selectAll" resultMap="brandResultMap">
    select * from tb_brand;
</select>
</mapper>

处理对于含有参数的查找时,XXXMapper.xml文件的配置

BrandMapper接口:

public interface BrandMapper {
    Brand selectById(int id);
    List<Brand> selectAll();
}

BrandMapper.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="Mapper.BrandMapper">
    <resultMap id="brandResultMap" type="pojo.Brand">
        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
    </resultMap>
    
<!--调用resultMap之后,select标签中的属性resultType改为resultMap-->
    <select id="selectAll" resultMap="brandResultMap">
        select * from tb_brand;
    </select>
    <!--下面的参数parameterType也可以不写-->
    <select id="selectById" parameterType="int" resultMap="brandResultMap">
        select * from tb_brand where id=#{id};
        <!--保持#{?}中?号处的参数和mapper接口中的参数一致即可-->
    </select>
</mapper>
<!--
    1.#{}:会将其替代为?,可以防止sql注入(类似于JDBC中的PrepareStatement)
    2.${}:拼接sql,会存在SQL注入问题b
    3.使用时机:
        参数传递的时候:#{}
        表名或者列名不固定的情况下:${}
    4.参数类型:parameterType:这个可以省略
    5.特殊字符的解决:
        <,>等符号在xml中要用特殊的字符代替
        1.转义字符
		2.CDATA区
		CDATA区的使用:
		<select id="selectById" resultMap="brandResultMap">
		select * from tb_brand where <![CDATA[<]]>#{id};
		</select>
-->

查询:查询所有数据和按照某个属性查询上面已经讲过,下面是条件查询。

条件查询:

1.多条件查询

参数接收有下面三种方式:
1.散装参数,使用@Param注解
List<Brand> selectByCondition(@Param("status")int status,@Param("companyName")String companyName,@Param("brandName")String brandName);
//@Param的作用就是告诉Mybatis将参数status传给.xml文件中的status,双引号中的是.xml文件中的参数。
2.对象参数:对象属性的名称要和参数占位符的名称一致
List<Brand> selectByCondition(Brand brand);
3.map集合参数
List<Brand> selectByCondition(Map map);

上面对应的java语句中的参数要传到下面的对应的值中。

<select id="selectByCondition" resultMap="brandResultMap">
	select *
	from tb_brand
	where
		status=#{status}
		and company_name like#{companyName}
        <!--模糊查询时,java程序中的参数要在前后加上%,否则会查询错误 -->
		and brand_name like#{brandName}
</select>		
int status=1;
String companyName="%华为%";
String brandName="%华%";
/*BrandMapper接口中的代码
List<Brand> selectByCondition(@Param("status") int status,@Param("companyName") String companyName, @Param("brandName") String brandName);
List<Brand> selectByCondition(Brand brand);
List<Brand> selectByCondition(Map map);*/
//使用散装参数查询
 List<Brand> brands1=brandMapper.selectByCondition(status,companyName,brandName);
 //使用对象参数
Brand brand_test=new Brand();
List<Brand> brands1=brandMapper.selectByCondition(brand_test);
//使用map集合
Map map_test=new HashMap();
map_test.put("status",status);
map_test.put("companyName",companyName);
map_test.put("brandName",brandName);
List<Brand> brands1=brandMapper.selectByCondition(map_test);
//上述三种方式的结果都是一样的

动态SQL查询:

动态SQL语句就是加入一些条件判断语句,处理参数为空的特殊情况

<select id="selectByCondition" resultMap="brandResultMap">
	select *
	from tb_brand
    <!--1=1是为了缓冲and,或者直接使用<where></where>标签-->
	<!--where 1=1-->
    <where>
    	<if test="status !=null">
            and status=#{status}
        </if>
        <if test="companyName !=null and companyName!=''">
            and company_name like#{companyName}
        </if>
        <!--模糊查询时,java程序中的参数要在前后加上%,否则会查询错误 -->
        <if test="brandName !=null and brandName!=''">
           and brand_name like#{brandName}
        </if>
    </where>   
</select>
<!--
mybatis中的动态sql
if
choose(when,otherwise)
trim(where,set)
foreach
-->

单条件的动态查询:

<select id="selectByConditionSingle" resultMap="brandResultMap">
    select *
    from tb_brand
    where
    <choose><!--类似于switch-->
        <when test="status!=null"><!--类似于case-->
            status=#{status}
        </when>
        <when test="companyName!=null and companyName!=">
            company_name like #{companyName}
        </when>
        <when test="brandName!=null and brandName!=''">
            brand_name like #{brandName}
        </when>
        <otherwise><!--类似于d-->
            1=1
        </otherwise>
    </choose>    
</select>

内容来自于该教程的总结:
https://www.bilibili.com/video/BV1Qf4y1T7Hx?p=56

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值