💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] # User ~~~ public class User implements Serializable { private Integer id; private String username; private Date birthday; private String sex; private String address; private static final long serialVersionUID = 7247714666080613254L; ~~~ 下面是代理DAO # 增加 接口 ~~~ public interface IUserDao { /** * 保存用户 * @param user */ void saveUser(User user); } ~~~ 注意User要有get和set ~~~ <!-- parameterType是参数类型 --> <insert id="saveUser" parameterType="com.jdxia.domain.User"> insert into user(username, address, sex, birthday) values (#{username}, #{address}, #{sex}, #{birthday}) </insert> ~~~ 执行代码 ~~~ @Test public void testSave() throws IOException { User user = new User(); user.setUsername("mybatis saveUser"); user.setAddress("地址"); user.setSex("男"); user.setBirthday(new Date()); userDao.saveUser(user); //提交事务,不然你看日志Setting autocommit to false on JDBC Connection //可以把这个放在关闭前 sqlSession.commit(); } ~~~ # 更新 接口 ~~~ /** * 更新用户 * @param user */ void updateUser(User user); ~~~ 配置文件 ~~~ <!-- 更新操作 --> <!-- parameterType是参数类型 --> <update id="updateUser" parameterType="com.jdxia.domain.User"> update user set username = #{username}, address = #{address}, sex = #{sex}, birthday= #{birthday} where id = #{id} </update> ~~~ 执行 ~~~ @Test public void testUpdate() throws IOException { User user = new User(); //如果这一行没有,他不会添加 user.setId(50); user.setUsername("mybatis updateUser"); user.setAddress("地址111"); user.setSex("男"); user.setBirthday(new Date()); userDao.updateUser(user); } ~~~ # 删除 接口 ~~~ /** * 删除用户 * @param id */ void deleteUser(Integer id); ~~~ 配置文件 ~~~ <delete id="deleteUser" parameterType="integer"> delete from user where id = #{id} </delete> ~~~ 执行 ~~~ @Test public void testDelete() throws IOException { userDao.deleteUser(51); } ~~~ # 查询 配置文件 ~~~ <!-- 配置查询所有 --> <select id="findAll" resultType="com.jdxia.domain.User"> select * from user </select> ~~~ 接口(如果写注解的话,配置要删掉,SqlMapConfig.xml那也要改) ~~~ /** * 查询所有操作 * @return List<User> */ //@Select("select * from user") List<User> findAll(); ~~~ 执行 ~~~ List<User> users = userDao.findAll(); for (User user : users) { System.out.println(user); } ~~~ # selectKey * keyProperty: selectKey语句结果应该被设置的目标属性 * keyColumn: 匹配属性的返回结果集中的列名称 * resultType: 结果的类型,mybatis通常可以推算出来,但是为了更加确定写上也不会有问题 * order: 可以设置为BEFORE或者AFTER.如果设置为BEFORE那么他会首先选择主键,设置keyProperty然后执行插入语句.如果设置为AFTER,那么先执行插入语句,然后是selectKey元素 * statementType: 与前面相同,mybatis支持STATEMENT,PREPARED和CALLABLE语句的映射类型,分别代表PreparedStatement和CallableStatement类型 # 获取主键 ## 方法一 ~~~ insert into user(username, address, sex, birthday) values ('xx', .....); select last_insert_id(); ~~~ 新增用户后,同时还要返回当前新增用户id的值,因为id是由数据库的自动增长来实现的,所以就相当于在新增后将自动增长auto_increment的值返回 **接口** ~~~ /** * 保存用户 * @param user * @return */ Integer saveUser(User user); ~~~ **配置文件** ~~~ <!-- parameterType是参数类型 --> <insert id="saveUser" parameterType="com.jdxia.domain.User"> <!-- keyProperty代表要返回值的名称 order:取值为AFTER代表插入后的行为,resultType是返回值类型 --> <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> select last_insert_id(); </selectKey> insert into user(username, address, sex, birthday) values (#{username}, #{address}, #{sex}, #{birthday}) </insert> ~~~ **执行** ~~~ User user = new User(); user.setUsername("mybatis saveUser"); user.setAddress("地址"); user.setSex("男"); user.setBirthday(new Date()); System.out.println("保存操作之前user: " + user); Integer id = userDao.saveUser(user); System.out.println("保存操作之后user: " + user); System.out.println("id是---" + id); ~~~ 看user前后变化 ~~~ 保存操作之前user: {"id":null,"username":"mybatis saveUser","birthday":"Sat Sep 28 13:18:21 CST 2019","sex":"男","address":"地址"} 保存操作之后user: {"id":55,"username":"mybatis saveUser","birthday":"Sat Sep 28 13:18:21 CST 2019","sex":"男","address":"地址"} ~~~ ## 方法二keyProperty 在mapper中指定keyProperty属性,示例如下: mybatis用的是`statement.getGenreatedKeys();` `useGeneratedKeys="true"`使用自增主键值获取主键策略 keyProperty指定对应主键属性,mybatis获取到,存到javaBean的那个属性 ~~~ <insert id="insertAndGetId" useGeneratedKeys="true" keyProperty="userId" parameterType="com.chenzhou.mybatis.User"> insert into user(userName,password,comment) values(#{userName},#{password},#{comment}) </insert> ~~~  如上所示,我们在insert中指定了keyProperty="userId",其中userId代表插入的User对象的主键属性。 ~~~ public class User { private int userId; private String userName; private String password; private String comment; //setter and getter } ~~~ ~~~ System.out.println("插入前主键为:"+user.getUserId()); userDao.insertAndGetId(user);//插入操作 System.out.println("插入后主键为:"+user.getUserId()); ~~~ ## oracle获取自增的主键 **里面sql不能带分号,oracle对书写有要求** ~~~ <!-- 获取非自增主键的值: Oracle不支持自增;Oracle使用序列来模拟自增; 每次插入的数据的主键是从序列中拿到的值;如何获取到这个值; --> <insert id="addEmp" databaseId="oracle"> <!-- keyProperty:查出的主键值封装给javaBean的哪个属性 order="BEFORE":当前sql在插入sql之前运行 AFTER:当前sql在插入sql之后运行 resultType:查出的数据的返回值类型 BEFORE运行顺序: 先运行selectKey查询id的sql;查出id值封装给javaBean的id属性 在运行插入的sql;就可以取出id属性对应的值 AFTER运行顺序: 先运行插入的sql(从序列中取出新值作为id); 再运行selectKey查询id的sql; --> <selectKey keyProperty="id" order="BEFORE" resultType="Integer"> <!-- 编写查询主键的sql语句 --> <!-- BEFORE--> select EMPLOYEES_SEQ.nextval from dual <!-- AFTER: select EMPLOYEES_SEQ.currval from dual --> </selectKey> <!-- 插入时的主键是从序列中拿到的 --> <!-- BEFORE:--> insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) values(#{id},#{lastName},#{email<!-- ,jdbcType=NULL -->}) <!-- AFTER: insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) values(employees_seq.nextval,#{lastName},#{email}) --> </insert> ~~~ # 为什么能直接写name,而不用写`user.name` 因为parameterType中已经提供了属性所属的类,所以不要写对象名. 他通过OGNL表达式来获取值,把get省略了 ## QVO ~~~ public class QueryVo { private User user; private Integer id; //setter/getter ~~~ **接口** ~~~ List<User> findByNameAndId(QueryVo vo); ~~~ **配置文件** ~~~ <!-- 根据用户id和name查询 --> <select id="findByNameAndId" resultType="com.jdxia.domain.User" parameterType="com.jdxia.domain.QueryVo"> <!-- user.username就是OGNL --> select * from user where username like #{user.username} and id = #{id} </select> ~~~ **执行** ~~~ User user = new User(); user.setUsername("%王%"); QueryVo queryVo = new QueryVo(); queryVo.setId(42); queryVo.setUser(user); List<User> res = userDao.findByNameAndId(queryVo); for (User u : res) { System.out.println(u); } ~~~ # 批量操作 一个是foreach标签 一个是jdbc数据库连接属性的`allowMultiQueries=true`,sql要;分割