• crud即增删改查 r是检索的意思,对应select


  • 增、删、改操作需要提交事务!不写的话不会真正提交到数据库
  • idea中会显示你执行成功了,但是到系统的mysql命令行里查询数据,会发现没有执行成功,数据没有变化

    mybatis中的自动序列化

  • mybatis接收sql或者传递参数到sql中时,可以直接保存为实体类或者传递一个实体类。mybatis可以自动根据实体类对象的属性进行序列化或者反序列化,然后与sql进行字段映射

    • 映射方式为字段名映射
  • 插入和查询多字段时会经常使用对象接收与传入。

    更多反序列化方式

  • 多个同类型数据时可以采用list进行接收,对于bean可以自动接收为实体对象,map。甚至可以接收为List<Map<,>>

    • mybatis自动映射本质是调用set,get方法
    • 实体类与数据库类字段不一致时可以通过给sql语句增加别名来配置

      参数映射

  • 一个基本类或基本类型参数使用#可以不需要@Param,名称也可以不对应。如果使用了@Param,则名称必须对应

    • 如果使用$,则必须@Param,自然参数名称得对应
  • map直接#{键},不能使用@Param。$不清楚
  • bean时如果使用#。如果$/#{bean.属性} 必须使用@Param,参数为要对应的对象名称。如果$/#{bean.属性}则不能使用@Param
    • 注意$时引号问题
  • 多个基本类或基本类型必须@Param

  • @Param对应xml**parameterType属性**

  1. 在接口方法中,参数直接传递MapUser selectUserByNP2(Map<String,Object> map);
  2. 编写sql标签的时候,需要设置参数类型属性,参数类型为map.
    1. 注解则直接写通配符sql即可
      1. <select id="selectUserByNP2" parameterType="map" resultType="com.kuang.pojo.User">
      2. select * from user where name = #{username} and pwd = #{pwd}
      3. </select>

      Select

      模糊查询

  • 在java中拼接出模糊查询子句然后传入sql ```java selectlike(); //模糊查询方法

TestString aa = “%smi%”; list names = mapper.selectlike(aa); //测试


<a name="ndKGM"></a> ## 关联查询 1. 方法1是直接写连接查询sql 1. 2则是通过mybatis的关联功能查 <a name="AKsB8"></a> # Insert Update Delete - **这三种操作需要提交事务才会事务才会被数据库保存操作结果** - **增删改返回值即成功操作的数量**java int addUser(User user);//添加一个用户 int updateUser(User user); int deleteUser(int id); ```java <insert id="addUser" parameterType="com.kuang.pojo.User">//不需要返回类型属性 insert into user (id,name,pwd) values (#{id},#{name},#{pwd}) </insert> <delete id="deleteUser" parameterType="int"> delete from user where id = #{id} </delete> <update id="updateUser" parameterType="com.kuang.pojo.User"> update user set name=#{name},pwd=#{pwd} where id = #{id} </update> java User user = new User(5,"王五","zxcvbn");//创建一个User存储sql语句的参数,需要创建一个构造方法 int i = mapper.addUser(user); // System.out.println(i);//这个i没什么意义,应该是告诉你执行一次addUser,可以把方法改为void session.commit(); //提交事务 session.close(); } ----------------------------- @Test User user = mapper.selectUserById(1);//选择要修改的数据,虽然是查询,但是不输出查询结果 user.setPwd("asdfgh");//通过set方法修改User对象属性值 int i = mapper.updateUser(user);//执行修改,把所有user属性重新传递一遍 System.out.println(i); session.commit(); //提交事务,重点!不写的话不会提交到数据库 session.close(); } -------------------------------------- int i = mapper.deleteUser(5);//删除id为5的数据 System.out.println(i); session.commit(); //提交事务,重点!不写的话不会提交到数据库 session.close(); } ## 主键 - 主键配置一般是insert时需要配置,因为主键是唯一且非空的,传入错误的主键或者未传入主键时均容易出错,报的错一般是参数类型不匹配不唯一等等 ,虽然实际上跟参数类型没关系 - useGeneratedKeys="true/false"表示是否为自增主键,非自增时必须传入一个唯一主键值,自增时可以不传入,自动生成 - keyProperty="" 参数为实体类中作为主键的属性 - keyColumn="" 参数为数据库中的主键字段 - 还可以使用selectKey标签完成 ,selectKey 更加灵活,支持一定程度的自定义 java xml: <insert id="insertSelective" parameterType="com.xxx.dataobject.UserDo" keyColumn="id"" keyProperty="id" useGeneratedKeys="true"></insert> 注解: @Insert("INSERT INTO user(name,age) VALUES(#{user.name},#{user.age})") @Options(useGeneratedKeys=true, keyProperty="id", keyColumn="id") public int insertOne(@Param("user")User user); xml <insert id="insertUser" parameterType="User"> <selectKey keyProperty="id" order="AFTER" resultType="int"> select LAST_INSERT_ID() //查询最后一次插入时的id </selectKey> insert into tb_player (id, playName, playNo,team, height) values ( #{id,jdbcType=INTEGER}, #{playName,jdbcType=VARCHAR}, #{playNo,jdbcType=INTEGER}, #{team,jdbcType=VARCHAR}, #{height,jdbcType=DECIMAL} ) </insert> # 批量操作 - 批量操作时最好使用事务管理以保证多条语句的原子性 - 批量操作的本质就是一次性执行多条sql,避免多次访问数据库。 - 批量更新时需要在数据库连接配置处添加&allowMultiQueries=true。作用是允许sql里有分号;有的教程说还要加&rewriteBatchedStatements=true设置,作用是允许批量执行 - mybatis中批量操作有3种方法: 1. java循环调用sql 1. 使用mybatis的foreach 1. 使用mybatis提供的批处理执行器**BatchExecutor** - 速度:c>b>a b在循环数据量很大时可能会使得sql大小超过了MySQL服务器中max_allowed_packet变量的值时,会导致操作失败,抛出PacketTooBigException异常。 ## Executor - MyBatis 有三种基本的 Executor 执行器,SimpleExecutorReuseExecutorBatchExecutor - 执行器的生命周期只存在于当前**SqlSession** - SimpleExecutor每执行一次 update 或 select,就开启一个 Statement 对象,用完立刻关闭 Statement 对象。(这是默认的执行器) - ReuseExecutor可重用执行器:执行 update 或 select,以 sql 作为 key 查找 Statement 对象,存在就使用,不存在就创建,用完后,不关闭 Statement 对象,而是放置于 Map内,供下一次使用。简言之,就是重复使用 Statement 对象。 - **BatchExecutor批处理执行器**执行 update(没有 select,JDBC 批处理不支持 select),将所有 sql 都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个 Statement 对象,每个 Statement 对象都是 addBatch()完毕后,等待逐一执行 executeBatch()批处理。(本质还是JDBC的批处理) java @Autowired private SqlSessionTemplate sqlSessionTemplate; List<User> list=...; SqlSessionFactory sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory(); //指定使用哪种执行器,而不是使用默认的执行器 SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false); //获取Mapper对象 UserMapper userMapper = sqlSession.getMapper(Usermapper.class); Integer size = list.size(); try { for (int i = 0; i < size; i++) { User user = list.get(i); userMapper.insertUser(user); if (i % 1000 == 0 || i == size - 1) { sqlSession.commit(); sqlSession.clearCache(); } } }catch (Throwable throwable){ sqlSession.rollback(); //抛出异常回滚 throwable.printStackTrace(); }finally { sqlSession.close(); } # 动态sql(xml版) ActivitiesMapper.xml - if
- choose (when, otherwise) - when子句有一个成立就退出,不执行剩下地when。如果when都不成立,就执行otherwise。类似switch-case-break-default - where有返回值时就会插入where,此外,如果标签返回的内容是以and 或or 开头的,则它会剔除掉。 - trim (where, set) - foreach,循环对象集合貌似必须是map,所以对于list必须存入map中传到foreach中 - open:条件的开始 - close:条件的结束 - separator每一次循环的连接 - sql,include:提取公用的sql片段,使用include引入 - 最好基于 单表来定义 sql 片段,提高片段的可重用性 - 在 sql 片段中不要包括 where ```xml select from blog where 1=1 //根据标题与作者名查找
and title = #{title}
and author = #{author} //—————动态拼接时除了1=1防止语法出错,还可以通过where,where有返回值时就会插入where,此外,如果标签返回的内容是以and 或or 开头的,则它会剔除掉。 ```xml <!--set有返回值时会添加逗号,如果是最后一个=则不添加逗号 --> <update id="updateBlog" parameterType="map"> update blog <set> <if test="title != null"> title = #{title}, </if> <if test="author != null"> author = #{author} </if> </set> where id = #{id}; </update> ```xml ```xml <sql id="if-title-author"> //id为sql的标识,include通过refid和id绑定sql <if test="title != null"> title = #{title} </if> <if test="author != null"> and author = #{author} </if> </sql> <select id="queryBlogIf" parameterType="map" resultType="blog"> select * from blog <where> <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace --> <include refid="if-title-author"></include> <!-- 在这里还可以引用其他的 sql 片段 --> </where> </select> ```xml

HashMap map = new HashMap(); List ids = new ArrayList(); ids.add(1); ids.add(2); map.put(“ids”,ids); List blogs = mapper.queryBlogForeach(map);

```xml
 <insert id="insertBatch">
    INSERT INTO tb_student (name, age, phone, address, class_id) VALUES
    <foreach collection="list" separator="," item="item">
        (#{item.name},#{item.age},#{item.phone},#{item.address},#{item.classId})
    </foreach>
  </insert>

int insertBatch(List<Student>)

更多MyBatis和Mapper配置选项

链接

MyBatis生命周期与作用域

链接

延迟加载

  • 这里只是提一下,就是使用mybatis多表连接时,不是一次性把所有关联表数据都查出来,而是先查出主表,副表的数据后面再去查询,防止每次不一定需要附表数据而过多消耗时间