## 开发流程 ### 前言 在前面JDBC的学习中,虽然我们能够通过JDBC来连接和操作数据库,但是这实在是太麻烦了,哪怕只是完成一个SQL语句的执行,都需要编写大量的代码,更不用说如果我还需要进行实体类映射,将数据转换为我们可以直接操作的实体类型,JDBC虽然进行了接口的定义,但是还不够方便,我们需要一种更加简洁高效的方式来和数据库进行交互。 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。 ### 数据库 创建数据库 设计表 \~\~\~java CREATE DATABASE test1 CHARACTER SET utf8; USE test1; CREATE TABLE \`db_user\` ( \`uid\` int NOT NULL AUTO_INCREMENT, \`uname\` varchar(255) NOT NULL, \`uage\` int DEFAULT NULL, \`upwd\` varchar(255) NOT NULL, \`utel\` varchar(255) NOT NULL, \`ugender\` varchar(255) NOT NULL, PRIMARY KEY (\`uid\`), UNIQUE KEY \`utel\` (\`utel\`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb3; -- ---------------------------- -- Records of db_user -- ---------------------------- INSERT INTO \`db_user\` VALUES ('1', '张三', '18', '111111', '1233211234567', '男'); INSERT INTO \`db_user\` VALUES ('2', '里斯', '18', '222222', '1233211234789', '女'); INSERT INTO \`db_user\` VALUES ('3', '豆豆', '22', '333333', '1233211234000', '男'); INSERT INTO \`db_user\` VALUES ('4', '王五', '21', '444444', '1233211234444', '男'); INSERT INTO \`db_user\` VALUES ('5', '张三丰', '17', '123456', '11122233345', '女'); \~\~\~ ### 新建Maven项目 新建Maven项目 确定组名 项目名 编写pom.xml配置文件 添加mysql依赖 添加Lombok依赖 添加myBatis依赖 \~\~\~xml 4.0.0 com.woniuxy Test9 1.0-SNAPSHOT 17 17 org.projectlombok lombok 1.18.30 com.mysql mysql-connector-j 8.3.0 org.mybatis mybatis 3.5.16 \~\~\~ ### 实体类 创建包 创建实体类 使用lombok \~\~\~java package com.woniuxy.entity; import lombok.Data; @Data public class User { private int uId; private String uName; private int uAge; private String uPwd; private String uTel; private String uGender; } \~\~\~ ### MyBatis配置文件 在项目下直接创建mybatis-config.xml \~\~\~xml \~\~\~ ### SqlSession 每一个SqlSession都代表一个会话,也就相当于我们之前通过命令行访问MySQL的一个窗口,不同会话之间相互隔离,不受影响。SqlSession接口中为我们预设了非常多的增删改查操作: \`\`\`\`java public interface SqlSession extends Closeable { T selectOne(String statement); T selectOne(String statement, Object parameter); List selectList(String statement); ... int insert(String statement); int insert(String statement, Object parameter); int update(String statement); int update(String statement, Object parameter); int delete(String statement); int delete(String statement, Object parameter); \`\`\`\` 可以看到,针对于增删改查这类操作,Mybatis已经把每一种操作都预设好了,并且查询的返回结果直接就是我们需要的实体类型,相比JDBC来说方便太多了。 #### 问题1:如何获取SqlSession \`SqlSessionFactoryBuilder\`---》\`SqlSessionFactory\`---》\`SqlSession\` \`SqlSessionFactoryBuilder\`用于构建\`SqlSessionFactory\`对象,每个基于 MyBatis 的应用都是以一个\` SqlSessionFactory\` 的实例为核心的,由\`SqlSessionFactory \`可以创建无数会话(\`SqlSession\`) 编写资源类com.woniuxy.basedaoimpl.MyBatisUtil便于快速获取连接会话 默认为手动提交 \`\`\`java package com.woniuxy.basedaoimpl; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.FileInputStream; import java.io.FileNotFoundException; //封装一个获取SqlSession的工具类 public class MybatisUtils { private static SqlSession session; public static SqlSession getSession(boolean autoCommit) throws FileNotFoundException { if(session==null){ SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(new FileInputStream("mybatis-config.xml")); //设置该连接为自动提交(默认手动提交) session = ssf.openSession(autoCommit); } return session; } public static void closeSession(){ if(session!=null){ session.close(); session = null; } } } \`\`\` #### 问题2:如何使用SqlSession中的功能 那么如何去使用\`SqlSession\`这些方法呢?Mybatis并不知道我们具体需要执行的SQL语句,以及需要返回哪些数据作为结果,因此我们同样需要编写配置文件来告诉Mybatis我们要做什么。 1》非maven项目中,在项目目录下创建一个新的\`mappers\`目录,然后创建一个新的文件\`UserMapper.xml\`作为我们的SQL语句映射配置。在mybatis-config.xml的前添加标签,做如下配置: \`\`\`xml \`\`\` 2》maven项目中,在resources文件夹中创建UserMapper.xml,则在在mybatis-config.xml的前添加标签,做如下配置: \`\`\`xml \`\`\` 接下来就是如何编写UserMapper.xml数据映射配置文件了 ### 数据映射配置文件 \~\~\~xml select \* from db_user select count(uid) from db_user select \* from db_user where uage between #{age1} and #{age2} select \* from db_user where uid = #{uid} select \* from db_user where uid = #{uid} select \* from db_user where uid = #{uid} select \* from db_user where uid = #{uid} and ugender = #{ugender} select \* from db_user where uage \>= #{uage1} and uage \<= #{uage2} select \* from db_user where ugender = #{ugender} 关闭自动映射 select \* from db_user where uage = #{uage} 关闭自动映射 \~\~\~ namespace:目前随便起名,后面会有要求 但是不能不写 不能为null 在MyBatis配置文件中给实体类路径起别名方便使用 \`\`\`xml 。。。 。。。 \`\`\` ### 功能层1 \~\~\~java //获取SqlSession会话 参数true自动提交 SqlSession session = MyBatisUtil.getSession(true); //根据sql需求选择SqlSession中合适的方法 传入数据映射配置文件中对应sql的id List users = session.selectList("selAllUser"); //展示结果 users.forEach(System.out::println); User(uId=1, uName=张三, uAge=18, uPwd=111111, uTel=1233211234567, uGender=男) User(uId=2, uName=里斯, uAge=18, uPwd=222222, uTel=1233211234789, uGender=女) User(uId=3, uName=豆豆, uAge=22, uPwd=333333, uTel=1233211234000, uGender=男) User(uId=4, uName=王五, uAge=21, uPwd=444444, uTel=1233211234444, uGender=男) User(uId=5, uName=张三丰, uAge=17, uPwd=123456, uTel=11122233345, uGender=女) //id条件查询 // User user = session.selectOne("selUserById", 2); // System.out.println(user);//User(uid=2, uname=里斯, upwd=222222, utel=1233211234789, ugender=女) //没有实体类可以返回Map集合 // Map os = session.selectOne("selById", 2); // System.out.println(os);//{utel=1233211234789, uid=2, uname=里斯, ugender=女, upwd=222222} //根据id年龄共同查询 // User user = session.selectOne("selUserByIdAndAge", Map.of("uid", 1,"uage",18)); // System.out.println(user); //根据id性别共同查询 // User user = session.selectOne("selUserByIdAndGender", Map.of("uid", 2,"ugender","女")); // System.out.println(user); // @AllArgsConstructor // class Param{ // int uage; // String ugender; // } //自定义一个成员内部类作为条件存储对象传入 要求该类属性名称 顺序 类型与数据库中一致 // User user = session.selectOne("selUserByIdAndGender", new Param(2,"女")); // System.out.println(user); // List users = session.selectList("selUserByAges", Map.of("uage1", 18, "uage2", 21)); // users.forEach(System.out::println); //可以将查询出的对象作为值 单独取某一列作为键 返回键值对 // Map musers = session.selectMap("selAllUser", "uid"); // System.out.println(musers); // musers.forEach((o1,o2)-\> System.out.println(o1+"\~"+o2)); //该方法返回实现了迭代器的游标 // Cursor cu = session.selectCursor("selAllUser"); // for (User u : cu){ // System.out.println(u); // } //通过回调形式获取结果 第二个参数是函数式接口ResultHandler //session.select("selAllUser",resultContext -\> System.out.println(resultContext.getResultObject())); //选定某个手动编写的构造方法创建对象 List users = session.selectList("selUserByGender", "女"); users.forEach(System.out::println); //uage属性配置了 接收了 因此可以由指定构造方法操作 // User(uid=2, uname=里斯, uage=38, upwd=222222, utel=1233211234789, ugender=女) // User(uid=5, uname=张三丰, uage=37, upwd=123456, utel=11122233345, ugender=女) // List users = session.selectList("selUserByAge", 18); // users.forEach(System.out::println); //uname属性并没有在mapper中配置 构造方法也没有接收 则依然走反射 // User(uid=1, uname=张三, uage=18, upwd=111111, utel=1233211234567, ugender=妖) // User(uid=2, uname=里斯, uage=18, upwd=222222, utel=1233211234789, ugender=妖) //关闭会话(事务) MybatisUtils.closeSession(); \~\~\~ ### 映射接口类(签名) 为了更方便调用映射文件中的sql 创建一个接口类UserMapper 1.在src中com.woniuxy.mapper文件夹中创建一个接口类UserMapper 2.以UserMapper.xml文件中每个sql的id为方法名 选择合适返回值 及 参数设计方法 3.要求UserMapper.xml文件 mapper标签的namespace的值必须是该接口的路径com.woniuxy.mapper.UserMapper 4.mybatis-config.xml文件中标签改为指向接口类 \`\`\`xml select \* from db_user select count(uid) from db_user select \* from db_user where uage between #{age1} and #{age2} select \* from db_user where uid = #{uid} \`\`\` \`\`\`java package com.woniuxy.mapper; import com.woniuxy.entity.User; import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; public interface UserMapper { List selAllUser(); int selCount(); //多个参数 方案一 List selUserByAges(Map mii); //多个参数方案二 //List selUserByAges(int age1,int age2); //多个参数方案三 List selUserByAges(@Param("age1")int age1, @Param("age2") int age2); User selUserById(int id); } \`\`\` \`\`\`xml \`\`\` ### 功能层2 \`\`\`java package com.woniuxy; import com.woniuxy.basedaoimpl.MyBatisUtil; import com.woniuxy.entity.User; import com.woniuxy.mapper.UserMapper; import org.apache.ibatis.session.SqlSession; import java.io.FileNotFoundException; import java.util.List; public class Main { public static void main(String\[\] args) throws FileNotFoundException { System.out.println("Hello world!"); //1.获取会话 SqlSession session = MyBatisUtil.getSession(true); //2.通过动态代理 获得UserMapper接口类的实现类对象 UserMapper um = session.getMapper(UserMapper.class); //3.调用MyBatis自动实现的方法 List users = um.selAllUser(); users.forEach(System.out::println); Scanner input = new Scanner(System.in); System.out.println("请输入最小年龄"); int a1 = input.nextInt(); System.out.println("请输入最大年龄"); int a2 = input.nextInt(); //多参方案1 传入Map键值对 //对应的接口方法List selUserByAges(Map mii); //xml中 select \* from db_user where uage between #{age1} and #{age2} // List us1 = um.selUserByAges(Map.of("age1",a1,"age2",a2)); // us1.forEach(System.out::println); //多参方案2 直接传值 //对应的接口方法List selUserByAges(int age1,int age2); //xml中 select \* from db_user where uage between #{param1} and #{param2} //必须叫param1 param2 一次排列开 // List us1 = um.selUserByAges(a1,a2); // us1.forEach(System.out::println); //多参方案3 直接传值 //对应接口方法List selUserByAges(@Param("age1")int age1, @Param("age2") int age2); //通过注解 将形参定死 //xml中select \* from db_user where uage between #{age1} and #{age2} List us1 = um.selUserByAges(a1,a2); us1.forEach(System.out::println); //不适用签名 之前做法 // List us1 = session.selectList("selUserByAges", Map.of("age1", a1, "age2", a2)); // us1.forEach(System.out::println); // User(uId=1, uName=张三, uAge=18, uPwd=111111, uTel=1233211234567, uGender=男) // User(uId=2, uName=里斯, uAge=18, uPwd=222222, uTel=1233211234789, uGender=女) // User(uId=5, uName=张三丰, uAge=17, uPwd=123456, uTel=11122233345, uGender=女) System.out.println(); // System.out.println("请输入要查询用户的id"); // int id = input.nextInt(); // User user = um.selUserById(id); // System.out.println(user); } } User(uId=1, uName=张三, uAge=18, uPwd=111111, uTel=1233211234567, uGender=男) User(uId=2, uName=里斯, uAge=18, uPwd=222222, uTel=1233211234789, uGender=女) User(uId=3, uName=豆豆, uAge=22, uPwd=333333, uTel=1233211234000, uGender=男) User(uId=4, uName=王五, uAge=21, uPwd=444444, uTel=1233211234444, uGender=男) User(uId=5, uName=张三丰, uAge=17, uPwd=123456, uTel=11122233345, uGender=女) \`\`\` ### 复杂查询 一对一业务查询 \`\`\`java DROP TABLE IF EXISTS \`db_userdetail\`; CREATE TABLE \`db_userdetail\` ( \`uid\` int NOT NULL AUTO_INCREMENT, \`uname\` varchar(255) NOT NULL, \`uage\` int NOT NULL, PRIMARY KEY (\`uid\`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb3; -- ---------------------------- -- Records of db_userdetail -- ---------------------------- INSERT INTO \`db_userdetail\` VALUES ('1', '张三', '18'); INSERT INTO \`db_userdetail\` VALUES ('2', '李四', '22'); INSERT INTO \`db_userdetail\` VALUES ('3', '王五', '19'); INSERT INTO \`db_userdetail\` VALUES ('4', '马六', '21'); INSERT INTO \`db_userdetail\` VALUES ('5', '田七', '21'); DROP TABLE IF EXISTS \`db_usermessage\`; CREATE TABLE \`db_usermessage\` ( \`uid\` int NOT NULL AUTO_INCREMENT, \`uaddress\` varchar(255) NOT NULL, \`uschool\` varchar(255) NOT NULL, PRIMARY KEY (\`uid\`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb3; -- ---------------------------- -- Records of db_usermessage -- ---------------------------- INSERT INTO \`db_usermessage\` VALUES ('1', '北京', '蜗牛一小'); INSERT INTO \`db_usermessage\` VALUES ('2', '重庆', '蜗牛一中'); INSERT INTO \`db_usermessage\` VALUES ('3', '重庆', '蜗牛二中'); db_userdetail表与db_usermessage表通过Id 属于一对一业务查询 package com.woniuxy.entity; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.FieldDefaults; //切记一定要有空参构造 @Data @FieldDefaults(level = AccessLevel.PRIVATE) @NoArgsConstructor @AllArgsConstructor public class UserMessage { int uid; String uaddress; String uschool; } @Data @FieldDefaults(level = AccessLevel.PRIVATE) @NoArgsConstructor @AllArgsConstructor public class UserDetail { int uid; String uname; int uage; UserMessage userMessage; } UserMessage类为UserDetail类的一个属性 作为用户详细信息 \`\`\` 需求:希望通过id获取两张表中该用户信息 使用:嵌套结果映射 \`\`\`xml select \* from db_userdetail left join db_usermessage on db_userdetail.uid = db_usermessage.uid where db_userdetail.uid = #{id} \`\`\` 一对多业务 需求:创建一张图书表 每位用户可以借用多本图书 同时查出当前id用户的所有图书 \`\`\`java DROP TABLE IF EXISTS \`db_book\`; CREATE TABLE \`db_book\` ( \`bid\` int NOT NULL AUTO_INCREMENT, \`bname\` varchar(255) NOT NULL, \`uid\` int NOT NULL, PRIMARY KEY (\`bid\`), KEY \`uid\` (\`uid\`), CONSTRAINT \`uid\` FOREIGN KEY (\`uid\`) REFERENCES \`db_userdetail\` (\`uid\`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb3; -- ---------------------------- -- Records of db_book -- ---------------------------- INSERT INTO \`db_book\` VALUES ('1', 'aaa', '1'); INSERT INTO \`db_book\` VALUES ('2', 'bbb', '1'); INSERT INTO \`db_book\` VALUES ('3', 'ccc', '1'); INSERT INTO \`db_book\` VALUES ('4', 'ddd', '2'); INSERT INTO \`db_book\` VALUES ('5', 'eee', '2'); INSERT INTO \`db_book\` VALUES ('6', 'fff', '3'); INSERT INTO \`db_book\` VALUES ('7', 'ggg', '3'); INSERT INTO \`db_book\` VALUES ('8', 'hhh', '3'); //设计对应实体类 package com.woniuxy.entity; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.FieldDefaults; //切记一定要有空参构造 @Data @FieldDefaults(level = AccessLevel.PRIVATE) @NoArgsConstructor @AllArgsConstructor public class Book { int bid; String bname; int uid; } 为UserDetail类添加 List lbooks; 属性 \`\`\` \`\`\`xml select \* from db_userdetail left join db_book on db_userdetail.uid = db_book.uid where db_userdetail.uid = #{id} \`\`\` 思考多对一 提供代码参考 \`\`\`xml xxx \`\`\` ### DML操作 前面我们介绍了查询操作,我们接着来看修改相关操作。Mybatis为我们的DML操作提供了几个预设方法: \`\`\`java int insert(String statement); int insert(String statement, Object parameter); int update(String statement); int update(String statement, Object parameter); int delete(String statement); int delete(String statement, Object parameter); \`\`\` 可以看到,这些方法默认情况下返回的结果都是\`int\`类型的,这与我们之前JDBC中是一样的,它代表执行SQL后受影响的行数。 我们来尝试编写一个插入操作,Mybatis为我们提供的插入操作非常快捷,我们可以直接让一个User对象作为参数传入,即可在配置中直接解析其属性到insert语句中,这里需要用到insert标签: \`\`\`xml insert db_user values (null,#{uname}, #{uage},#{ugender}) \`\`\` 需求: 有些时候,我们的数据插入后使用的是一个自增主键ID,那么这个自增的主键值我们该如何获取到呢?Mybatis为我们提供了一些参数用于处理这种问题: \`\`\`xml insert db_user values (null,#{uname}, #{uage},#{ugender}) \`\`\` \`useGeneratedKeys\`设置为\`true\`表示我们希望获取数据库生成的键, \`keyProperty\`设置为User类中的需要获取自增结果的属性名, \`keyColumn\`为数据库中自增的字段名称,但是一般情况下不需要手动设置,但是某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,必须设置。 设计接口方法:必须以对象作为参数方案 这样才能有对象的属性去接收返回的主键值 \`\`\`java //注意返回类型必须是int或是long这类数字类型,表示生效的行数,然后这里我们传入的参数直接写成对应的类型即可。 public int addUser(User user); \`\`\` 实现类中: \`\`\`java public void addUsers(){ //获取会话 SqlSession ss = MybatisUtil.getSs(true); //获取签名类动态代理生成的实现类对象 UserMapper um = ss.getMapper(UserMapper.class); //传入对象 则返回的主键才能有属性保存 User user = new User("李大花",17,"女"); int num = um.addUser(user); System.out.println(num); //展示返回的受影响行数 //获取新增行主键列的值 System.out.println(user.getUid()); //会看到参数对象的uid获取了数据库中该对象主键的值 } \`\`\` 我们接着来看修改操作,比如要根据ID修改用户的年龄: \`\`\`xml update user set age = #{age} where id = #{id} \`\`\` \`\`\`java int setUserAgeById(User user); \`\`\` 这里的参数我们依然选择使用User,和之前insert一样,Mybatis会从传入的对象中自动获取需要的参数,当然我们也可以将此方法设计为两个参数的形式: \`\`\`java int setUserAgeById(@Param("age") int age, @Param("id") int id); \`\`\` 删除操作则更为简单,假设我们要根据用户的id进行数据的删除: \`\`\`xml delete from user where id = #{id} \`\`\` 这些操作相比查询操作来说非常简单就可以实现,这里就不多做介绍了。 ### 事务操作 我们可以在获取\`SqlSession\`关闭自动提交来开启事务模式,和JDBC其实都差不多,在创建SqlSession的时候不填写参数默认使用的就是事务模式: \`\`\`java try (SqlSession session = sqlSessionFactory.openSession(false)) { ... } \`\`\` 我们发现,在关闭自动提交后,我们的内容是没有进入到数据库的: \`\`\`java try(SqlSession session = MybatisUtils.openSession(false)) { TestMapper mapper = session.getMapper(TestMapper.class); mapper.deleteUserById(1); //虽然日志中已经提示生效1行,但是并没有提交 } \`\`\` SqlSession接口中为我们提供了事务操作相关的方法,这里我们可以直接尝试进行事务的提交: \`\`\`java TestMapper mapper = session.getMapper(TestMapper.class); mapper.deleteUserById(7); session.commit(); //通过SqlSession进行事务提交 \`\`\` 注意,如果我们在提交事务之前,没有进行任何的DML操作,也就是删除、更新、插入的其中任意一种操作,那么调用\`commit\`方法则不会进行提交,当然如果仍然需要提交的话也可以使用\`commit(true)\`来强制提交。 我们接着来测试一下回滚操作: \`\`\`java TestMapper mapper = session.getMapper(TestMapper.class); mapper.deleteUserById(1); System.out.println(mapper.selectUserById(1)); //此时由于数据被删除,无法查到 session.rollback(); //进行回滚操作 System.out.println(mapper.selectUserById(1)); //之前被删除的数据回来了 \`\`\` 事务相关操作非常简单,这里就暂时先介绍这么多。 ### 批处理 需求:批量添加数据 为了查看到会话次数 开启Mybatis日志 \`\`\`xml .... \`\`\` 没有做批处理代码结构 userMapper.xml \`\`\`xml insert db_user values (null,#{uname},#{uage},#{ugender}) \`\`\` interface UserMapper \`\`\`java public int addUser(User user); \`\`\` class UserDaoImpl \`\`\`java public void addUsers(){ //获取会话 SqlSession ss = MybatisUtil.getSs(true); //获取签名类动态代理生成的实现类对象 UserMapper um = ss.getMapper(UserMapper.class); List lu = new ArrayList(); lu.add(new User("aaa",18,"女")); lu.add(new User("bbb",16,"男")); lu.add(new User("王cc",19,"男")); lu.add(new User("王dd",21,"女")); lu.add(new User("王ee",17,"男")); for (User u : lu) { um.addUser(u); } } \`\`\` 控制台日志 来回交互5次 \`\`\`tex Opening JDBC Connection Created connection 139947936. ==\> Preparing: insert db_user values (null,?,?,?) ==\> Parameters: aaa(String), 18(Integer), 女(String) \<== Updates: 1 ==\> Preparing: insert db_user values (null,?,?,?) ==\> Parameters: bbb(String), 16(Integer), 男(String) \<== Updates: 1 ==\> Preparing: insert db_user values (null,?,?,?) ==\> Parameters: 王cc(String), 19(Integer), 男(String) \<== Updates: 1 ==\> Preparing: insert db_user values (null,?,?,?) ==\> Parameters: 王dd(String), 21(Integer), 女(String) \<== Updates: 1 ==\> Preparing: insert db_user values (null,?,?,?) ==\> Parameters: 王ee(String), 17(Integer), 男(String) \<== Updates: 1 \`\`\` 以下采用批处理效果 \`\`\`java //1.获取会话时设定批处理模式 public static SqlSession getSession(boolean autoCommit) throws FileNotFoundException { if(session==null){ SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(new FileInputStream("mybatis-config.xml")); //session = ssf.openSession(autoCommit); //ExecutorType.BATCH 执行期类型改为批处理模式 session = ssf.openSession(ExecutorType.BATCH,autoCommit); } return session; } //2.采用批处理 批量进行预编译 还需要执行操作才能真正执行完毕 session.flushStatements(); \`\`\` 效果 \`\`\`tex Opening JDBC Connection Created connection 998062648. ==\> Preparing: insert db_user values (null,?,?,?) ==\> Parameters: 李aa(String), 18(Integer), 女(String) ==\> Parameters: 王bbb(String), 16(Integer), 男(String) ==\> Parameters: 马cc(String), 18(Integer), 男(String) ==\> Parameters: 李dd(String), 22(Integer), 女(String) ==\> Parameters: 王ee(String), 17(Integer), 女(String) \`\`\` ### 动态SQL 动态SQL在执行时可以进行各种条件判断以及循环拼接等操作,极大地提升了SQL语句编写的的灵活性。 #### if 需求:如果传入的年龄\>=18岁 则性别只要男生 String sql = "select \* from db_user where uage\>=18 and ugender='男' or uage\<18"; #{uage}\>=18 and ugender='男' if(uage\>=18){ select \* from db_user where uage\>=18 and ugender = '男' }else{ select \* from db_user where uage\<18 } \`\`\` xml select \* from db_user where uage = #{uage} and ugender = "男" select \* from db_user where ugender = #{ugender} and uage \>=18 如果提示缺少get方法 则需要去形参处定义@Param(形参名)类型 形参名 \`\`\` #### choose \`\`\`xml select \* from db_user where ugender = #{ugender} and uage \< 18 and uage \>= 18 \`\`\` #### foreach 需求:循环将list集合中的用户添加入数据表 \`\`\`xml insert into db_user values (null,#{item.uname},#{item.uage},#{item.ugender}) \`\`\` \`\`\`java public void addUsersByFor(){ SqlSession ss = MybatisUtil.getSs(true); UserMapper um = ss.getMapper(UserMapper.class); List list = new ArrayList(); list.add(new User("b李aa",18,"女")); list.add(new User("c王bbb",17,"男")); list.add(new User("d马cc",18,"男")); list.add(new User("e李dd",20,"女")); list.add(new User("a王ee",17,"女")); int num = um.addUsers(list); System.out.println(num); MybatisUtil.closeSs(); } \`\`\` \`\`\`tex ==\> Preparing: insert into db_user values (null,?,?,?) , (null,?,?,?) , (null,?,?,?) , (null,?,?,?) , (null,?,?,?) ==\> Parameters: b李aa(String), 18(Integer), 女(String), c王bbb(String), 17(Integer), 男(String), d马cc(String), 18(Integer), 男(String), e李dd(String), 20(Integer), 女(String), a王ee(String), 17(Integer), 女(String) \<== Updates: 5 \`\`\` ### 注解开发 只适合简单的sql语句 \`\`\`java @Select("select \* from tb_user where username=${username}") List getBywhere1(String username); \`\`\` Mybatis 针对 CURD 操作都提供了对应的注解,已经做到见名知意。如下: \* 查询 :@Select \* 添加 :@Insert \* 修改 :@Update \* 删除 :@Delete 如果同时需要使用xml和注解方法则mybatis核心文件中配置mappers需将xml文件放在下方 \`\`\`xml \`\`\`