Bootstrap

mybatis复习自用分享

mybatis作用简单来说就是简化jdbc,将jdbc的那些复杂。琐碎代码编程通透,简单,框架化的代码。

mybatis入门

首先如果是在建项目的时候就用了maven构建,那么可以直接在pom.xml配置文件中添加坐标,其中mybatis和mysql的坐标是必须的,junit测试单元和logback等其他坐标配置可以按需添加,如果在建项目的时候没有用maven构建,需要在后续的项目中添加maven构建的模块,名字也是pom.xml

上述解决后,便开始编写mybatis的核心配置文件。首先在resources中创建名为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 name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
      <!--加载sql映射文件-->
      <!--resource后面接的是映射文件路径-->
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

接着就是编写sql映射文件。在resources里面创建sql映射文件,命名格式为:表名Mapper,后缀为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">
  <!--
  namespace:名称空间
  id:sql语句的唯一标识
  resulrType:返回结果类型
  -->
<mapper namespace="org.mybatis.example.BlogMapper">
  <select id="selectBlog" resultType="Blog">
    select * from Blog where id = #{id}
  </select>
</mapper>

这个结束后,开始编码。步骤为:

1.定义pojo类,类里面就是一个个java文件。

2.加载核心配置文件,获取SQLSessionFactory

3.获取SqlSession对象,执行sql语句

4.释放资源

模板代码:

//加载mybatis的核心配置文件,获取SqlSessionFactory
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取SqlSession对象,用它来执行sql
SqlSession sqlSession=sqlSessionFactory.openSession();
//执行sql
//释放资源
sqlSession.close();

提示:在编写sql映射文件时,可能会有警告提示,原因可能是idea和数据库没有建立连接,所以建议开始就建连接。建立连接操作如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Mapper代理开发

Mapper代理开发也是为了简化上述代码。

Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);

上面这段代码就是原来的sql执行输出代码。

BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);

上面这个时用Mapper代理开发的sql执行输出代码。

mapper代理开发步骤:

1.定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下。下面图便是模板

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

提示:在编译后,UserMapper接口和UserMapper.xml在同一目录下。

2.设置SQL映射文件的namespace属性为Mapper接口全限定名。

即如下图所示:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.在Mapper接口中定义方法,方法名就是SQL映射文件中的sql语句中的id,并保证参数类型和返回值类型一致。

模板代码:

//加载mybatis的核心配置文件,获取SqlSessionFactory
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//获取SqlSession对象,用它来执行sql
SqlSession sqlSession=sqlSessionFactory.openSession();
//执行sql
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
List<User> users=userMapper.selectAll();
//释放资源
sqlSession.close();

细节:如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载。

eg:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这样在有很多sql映射文件时,可以用一行代码替代。

Mybatis核心配置文件

这个我不知道怎么讲,也说不清楚。索性贴配置的官网,在需要配置的时候直接查,不会的百度罢了。

配置链接:配置_MyBatis中文网

mybatis写项目必备插件:MyBatisX

查询

eg1:查询所有

<select id="函数名字" resultType="函数返回类型">
	select *
	from tb_brand(表名);
</select>

注意

如果数据库表的字段名称和实体类的属性名称不一样,则不能自动封装	    数据。
解决办法:起别名,对不一样的列名起别名,让别名和实体类的属性名一样
		<select id="函数名字" resultType="函数返回类型">
			select brand_name as brandName
			from tb_brand(表名);
		</select>
		缺点:每次查询都要定义一次别名
		
解决办法:sql片段
		<sql id="brand_column">
			id,brand_name as brandName
		</sql>
		<select id="函数名字" resultType="函数返回类型">
			select 
				<include refid="brand_column"/>
			from tb_brand(表名);
		</select>
		缺点:不灵活
		
解决办法:resultMap:1.定义<resultMap>标签,2.在select标签中,使用	    resulrMap属性替换resultType属性

		//id:唯一标识
		//type:映射的类型,支持别名
		<resultMap id="brandResultMap" type="brand">
            
		//id:完成主键字段的映射,column:表的列名,property:实体类				的属性名
		//result:完成一般字段的映射
        <result column="brand_name" 				`				property="brandName"/>
		<result column="company_name" 								property="companyName"/>
		</resultMap>
    
    	<select id="函数名字" resultMap="brandResultMap">
			select *
			from tb_brand(表名);
		</select>

eg2:查询详情

<!--
	参数占位符:
		1.#{}:会将其替换为?。可以防止SQL注入
		2.${}:拼SQL,会存在SQL注入问题
		3.使用时机:参数传递的时候用#{},表名或者列名不固定的情况下用			${}
-->

<select id="函数名字" resultType="函数返回类型">
	select *
	from tb_brand(表名) where id=#{id};
</select>

<!--
特殊字符处理:
	1.转义字符:
	2.CDATA区:
-->

特殊字符处理如果忘了,可以csdn上面搜。

eg3:条件查询

<select id="selectByCondition" resultMap="brandResuleMap">
	select *
	from tb_brand
	where
	status=#{status}
	and company_name like #{companyName}
	and brand_name like #{brandName};
	</select>

条件查询的参数接收问题

1.散装参数:如果方法中有多个参数,需要使用@Param(“SQL参数占位符名 称”)

eg:

List<Brand> selectByCondition(@Param("status") int status,@Param("companyName") int companyName)

2.对象参数:对象的属性名称要和参数占位符名称一致

eg:

List<Brand> selectByCondition(Brand brand);

3.map集合参数:需要保证SQL中的参数名和map集合的键的名称对应上,即可 设置成功

eg:

List<Brand> selectByCondition(Map map);

eg4:动态条件查询

动态查询:SQL语句会根据输入或者外部条件的变化而变化。

实现动态SQL的四个标签:

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

if的使用:

eg:

<select id="selectByCondition" resultMap="brandResuleMap">
	select *
	from tb_brand
	where
	<if test="status!=null">
		status=#{status}
	</if>
	<if test="companyName!=null and companyName!=''">
		and company_name like #{companyName}
	</if>
	<if test="brandName!=null and brandName!=''">
		and brand_name like #{brandName};
	</if>
	</select>

讲解:if:条件判断

​ test:逻辑表达式

但是上述动态sql语句有问题,如果第一个if标签没成立,那么这个sql语句就是错的。

解决办法:

方法1:恒等式
<select id="selectByCondition" resultMap="brandResuleMap">
	select *
	from tb_brand
	where 1=1
	<if test="status!=null">
		and status=#{status}
	</if>
	<if test="companyName!=null and companyName!=''">
		and company_name like #{companyName}
	</if>
	<if test="brandName!=null and brandName!=''">
		and brand_name like #{brandName};
	</if>
	</select>
	
	
	
	
方法2:where标签代替where关键字
<select id="selectByCondition" resultMap="brandResuleMap">
	select *
	from tb_brand
	<where>
	<if test="status!=null">
		and status=#{status}
	</if>
	<if test="companyName!=null and companyName!=''">
		and company_name like #{companyName}
	</if>
	<if test="brandName!=null and brandName!=''">
		and brand_name like #{brandName};
	</if>
	</where>
	</select>

eg5:单条件动态查询

<select id="selectByCondition" resultMap="brandResuleMap">
	select *
	from tb_brand
	<where>
	<choose><!--类似switch-->
	<when test="status!=null"><!--类似case-->
		and status=#{status}
	</when>
	<when test="companyName!=null and companyName!=''">
		and company_name like #{companyName}
	</when>
	<when test="brandName!=null and brandName!=''">
		and brand_name like #{brandName};
	</when>
	</where>
	</select>

添加

<insert id="add">
    insert into tb_brand (brand_name, company_name, ordered, description, status)
    values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>

这时候可能sql执行了,但是数据没有添加到数据库中,这很有可能是没有提交事务,导致发生sql回滚,然后数据就会添加不进去。

所以可以在执行的方法中,在释放资源前进行事务提交;即代码

//提交事务
    sqlSession.commit();

像下面这样也是可以的,在参数位置加一个true

sqlSessionFactory.openSession(true); //设置自动提交事务,这种情况不需要手动提交事务了

有时候可能需要返回主键的值,可以这样写SQL语句

<insert id="add" useGeneratedKeys="true" keyProperty="id">
    insert into tb_brand (brand_name, company_name, ordered, description, status)
    values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>

在 insert 标签上添加如下属性:

useGeneratedKeys:是够获取自动增长的主键值。true表示获取keyProperty :指定将获取到的主键值封装到哪儿个属性里

修改

eg1:

*set* 标签可以用于动态包含需要更新的列,忽略其它不更新的列。

<update id="update">
    update tb_brand
    <set>
        <if test="brandName != null and brandName != ''">
            brand_name = #{brandName},
        </if>
        <if test="companyName != null and companyName != ''">
            company_name = #{companyName},
        </if>
        <if test="ordered != null">
            ordered = #{ordered},
        </if>
        <if test="description != null and description != ''">
            description = #{description},
        </if>
        <if test="status != null">
            status = #{status}
        </if>
    </set>
    where id = #{id};
</update>

删除

eg1:删除一行

<delete id="deleteById">
    delete from tb_brand where id = #{id};
</delete>

eg2:批量删除

也就是将删除的行数以数组的形式告诉

foreach 标签

用来迭代任何可迭代的对象(如数组,集合)。

  • collection 属性:
    • mybatis会将数组参数,封装为一个Map集合。
      • 默认:array = 数组
      • 使用@Param注解改变map集合的默认key的名称
  • item 属性:本次迭代获取到的元素。
  • separator 属性:集合项迭代之间的分隔符。foreach 标签不会错误地添加多余的分隔符。也就是最后一次迭代不会加分隔符。
  • open 属性:该属性值是在拼接SQL语句之前拼接的语句,只会拼接一次
  • close 属性:该属性值是在拼接SQL语句拼接后拼接的语句,只会拼接一次
<delete id="deleteByIds">
    delete from tb_brand where id
    in
    <foreach collection="array" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
    ;
</delete>

后面还有一个参数传递,建议是啥都用@param()形式给出,避免报错。

还有一个SQL注解开发,建议是上面的学会就行,这个学不学都差不多,毕竟难的学会了,这简单的自然不在话下。

;