mybatis 进阶笔记

简单使用mybatis的增删改查

通过id查找到用户

使用的sql:

SELECT * FROM `user` WHERE id = 1

在user.xml中添加select标签,编写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:命名空间-->

<mapper namespace="test">

    <!-- id:statement的id 或者叫做sql的id-->

    <!-- parameterType:声明输入参数的类型 -->

    <!-- resultType:声明输出结果的类型,应该填写pojo的全路径 -->

    <!-- #{}:输入参数的占位符,相当于jdbc的? -->

    <select id="queryUserById" parameterType="int"

       resultType="cn.itcast.mybatis.pojo.User">

       SELECT * FROM `user` WHERE id  = #{id}

    </select>

</mapper>

测试程序步骤:

 1. 创建SqlSessionFactoryBuilder对象

 2. 加载SqlMapConfig.xml配置文件

 3. 创建SqlSessionFactory对象

 4. 创建SqlSession对象

 5. 执行SqlSession对象执行查询,获取结果User

 6. 打印结果

 7. 释放资源

public class MybatisTest {
	private SqlSessionFactory sqlSessionFactory;

	@Before
	public void before() throws Exception {
		// 1. 创建SqlSessionFactoryBuilder对象
		SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

		// 2. 加载SqlMapConfig.xml配置文件
		InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");

		// 3. 创建SqlSessionFactory对象
		this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
	}

	@Test
	public void testQueryUserById() throws Exception {
		// 4. 创建SqlSession对象
		SqlSession sqlSession = sqlSessionFactory.openSession();

		// 5. 执行SqlSession对象执行查询,获取结果User
		// 第一个参数是User.xml的statement的id,第二个参数是执行sql需要的参数;
		Object user = sqlSession.selectOne("test.queryUserById", 1);

		// 6. 打印结果
		System.out.println(user);

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

通过名字模糊查询

查询sql:

SELECT * FROM `user` WHERE username LIKE '%马%'

user.xml配置

<select id="selectUserByName" parameterType="String" resultType="com.fdw.pojo.User">
    SELECT * FROM t_user WHERE name like "%"#{name}"%"
</select>

测试

	@Test
	public void testQueryUserByUsername() throws Exception {
		// 4. 创建SqlSession对象
		SqlSession sqlSession = sqlSessionFactory.openSession();

		// 5. 执行SqlSession对象执行查询,获取结果User
		// 查询多条数据使用selectList方法
		List<Object> list = sqlSession.selectList("test.queryUserByUsername1", "马");

		// 6. 打印结果
		for (Object user : list) {
			System.out.println(user);
		}

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

#{}和${}

#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value

parameterType和resultType

parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。

resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器List中

 

selectOne和selectList

selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常

若是增删改的操作必须提交事务

增加用户

<insert id="addUser" parameterType="com.fdw.pojo.User">
      insert into t_user (name,sex,address,balance)
values (#{name},#{sex},#{address},#{balance})
  </insert>

-测试

@Test
public void testSaveUser() {
	// 4. 创建SqlSession对象
	SqlSession sqlSession = sqlSessionFactory.openSession();

	// 5. 执行SqlSession对象执行保存
	// 创建需要保存的User
	User user = new User();
	user.setName("张飞");
	user.setSex("1");
	user.setAddress("蜀国");

	sqlSession.insert("test.addUser", user);
	System.out.println(user);

	// 需要进行事务提交
	sqlSession.commit();

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

修改用户

  <update id="updateUser" parameterType="com.fdw.pojo.User">
      update t_user
set name = #{name},sex = #{sex},address = #{address},balance=#{balance},companyId=#{companyId}
where id = #{id}
  </update>

测试

@Test
public void testUpdateUserById() {
	// 4. 创建SqlSession对象
	SqlSession sqlSession = sqlSessionFactory.openSession();

	// 5. 执行SqlSession对象执行更新
	// 创建需要更新的User
	User user = new User();
	user.setId(26);
	user.setName("关羽");
	user.setSex("1");
	user.setAddress("蜀国");

	sqlSession.update("test.updateUser", user);

	// 需要进行事务提交
	sqlSession.commit();

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

删除用户

  <delete id="delUser" parameterType="Integer">
      delete from t_user
where id = #{superman}
  </delete>

    测试 

	@Test
	public void testDeleteUserById() {
		// 4. 创建SqlSession对象
		SqlSession sqlSession = sqlSessionFactory.openSession();

		// 5. 执行SqlSession对象执行删除
		sqlSession.delete("test.delUser", 48);

		// 需要进行事务提交
		sqlSession.commit();

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

 

Mybatis 与 hibernate 区别

Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。

 

Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。

 

Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。

总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。 

原始dao层开发

sqlSessionFactoryBuilder         读取配置文件  调用build方法

SqlSessionFactory                       创建 sqlsession

Sqlsession                  封装方法(每次都打开一个新的session)

Dao依赖于sqlSessionFactory

 

private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
    this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User selectUserById(Integer id) {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    return sqlSession.selectOne("test.selectUserById",id);
}

 

代理dao     (mapper接口) 开发

前提条件

  1. 接口方法名 == User.xm 的id名
  2. 返回值类型  与(Mapper.xm) 映射文件类型返回值类型一致
  3. 方法的入参类型与 映射文件中入参数类型一致
  4. 命名空间绑定此接口(namespace值与接口相对路径名一致)

接口名字 建议与 配置文件名字保持一致

注意事项:方法中的参数就只能有一个

       Selectone 与 selectList根据,mapper的返回值类型决定

SqlMapperConfig配置文件详解

    配置文件属性顺序必须如上图一致

TypeAliases   别名

<typeAliases>
   <typeAlias alias="User" type="com.fdw.pojo.User"></typeAlias>
   <package name="com.fdw.pojo"></package>
</typeAliases>

 

Typehandlers 类型处理器

    实现jdbc(数据库中的类型)和java类型的转换,一般不用自己去改,特殊情况下需要自己手动映射。

 Properties   设置属性

Settings   mybatis功能的设置

 

输入类型 和 输出类型

输入类型

普通类型

使用#{}占位符,或者${}进行sql拼接。

使用pojo类型

Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。

Pojo包装类  既包含普通类型也包含其他类型

包装对象:Pojo类中的一个属性是另外一个pojo。

输出类型

ResultType

自动装换(属性名 与数据库字段名一致)

ResultMap

手动转换 ,如果名字不一致则需要手动映射

<resultMap id="userxixi" type="com.fdw.pojo.User">
    <result property="password" column="psd"></result>
</resultMap>
<select id="selectUserById" parameterType="QueryVo" resultMap="userxixi">
    SELECT * FROM t_user WHERE id =#{id}
</select>

ResultMap: type 将要转换的类型

Id:主键      property实体类的属性名  column 数据库列的字段名

result     普通属性  

 

动态sql

If标签

<if test="id != '' and id != null">
  AND  id =#{id}
</if>
<if test="name != '' and name != null">
  AND name =#{name}
</if>

Test  使用ognl表达式的方式取值,可以if条件  并且and  或者 or

 

如果有多个条件,不知道是第一个成立and的位置不好放,放在任何一个位置都有可能有异常,使用where标签解决

Where标签     (自动去除前and)

 

若所有条件都不成立,那么where标签就去除

 

Foreach标签


<foreach collection="array" close=")" item="id" open="(" separator=",">
    #{id}
</foreach>

Collection 识别数据类型

       数组:array          set集合:set

      List集合:list    封装类:必须是封装类的属性名

<!-- item:遍历的元素,可以随便写,,但是和后面的#{}里面要一致 -->

       <!-- open:在前面添加的sql片段 -->

       <!-- close:在结尾处添加的sql片段 -->

       <!-- separator:指定遍历的元素之间使用的分隔符 -->

Index      下标

SQL片段


<sql id="userFields">

       id, username, birthday, sex, address

</sql>

SELECT <include refid="userFields" /> FROM `user`

Include refid 属性对应的就是     SQL片段的id名

多表查询

一对一

实现一对一查询的结果集封装

两种办法:

         ResultType

         新建一个实体类,这个实体类包含所有转换的列名

         可以建一个类,让这个类去继承一个类

<mapper namespace="com.fdw.manyTables.UserMapper">
    <select id="selectUser" resultType="com.fdw.manyTables.UserView">
        SELECT
        t_user.`name`,
        t_user.sex,
        t_user.address,
        t_user.balance,
        company.`name` AS companyname,
        company.address AS companyaddress,
        t_user.companyId,
        t_user.id
        FROM
        t_user
        LEFT JOIN company ON t_user.companyId = company.id
    </select>

 

         resultMap

         在user实体类中增加一个引用类的属性,并添加get-set方法,在结果集处理时采用

resultMap

<resultMap id="userView" type="user">
    <id property="id" column="id"></id>
    <result property="address" column="address"></result>
    <association property="company" javaType="company">
        <id property="id" column="company"></id>
        <result property="address" column="companyaddress"></result>
    </association>
</resultMap>

         若字段名和属性不写转换,就不会转化,要想将查询到的结果全部封装到实体类中,就必须全部都写

一对多

ResultType(不建议使用)

         新建一个实体类,这个实体类包含所有转换的列名

         可以建一个类,让这个类去继承一个类

 

ResultMap

添加属性 并添加get-set方法

<resultMap id="companyView" type="company">
    <id property="id" column="companyId"></id>
    <result property="name" column="companyName"></result>
    <collection property="users" javaType="list" ofType="user">
        <id property="id" column="id"></id>
        <result property="name" column="name"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
    </collection>
</resultMap>

Collection    property实体类的属性名,javaType(集合list set)

ofType     封装集合中每个元素的类型

 

(以下三种技术 可了解)

缓存(Redis   memache)

延迟加载                

逆向工程

逆向工程,通过一方生成另一方

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值