文章目录
增删改
增删改大同小异,没什么复杂的东西,只是标签不一样。
需要注意的是,增删改必须进行提交操作之后才会将改变提交给数据库。
Mybatis有以下获取session对象的方法,如果是第一种,需要手动提交事务;如果是第二种,传入参数true设置自动提交事务,false和第一种一样。
SqlSession openSession();
SqlSession openSession(boolean var1);
代码
以下是代码:
/**
* 添加用户
* @param user 一个用户实体信息封装类
*/
void insertUser(User user);
/**
* 修改用户
* @param user
*/
void updateUser(User user);
/**
* 删除用户
* @param id 要删除用户的ID
*/
void deleteUser(int id);
<insert id="insertUser" parameterType="com.modevil.domain.User">
INSERT INTO user(userName, sex, address) VALUES(#{userName}, #{sex}, #{address});
</insert>
<update id="updateUser" parameterType="com.modevil.domain.User">
UPDATE user SET userName=#{userName}, sex=#{sex},address=#{address} WHERE id=#{id}
</update>
<delete id="deleteUser" parameterType="com.modevil.domain.User">
DELETE FROM user WHERE id=#{id}
</delete>
对于标签中的属性
- id:对应方法名
- parameterType:对应输入的参数类型
获取执行的结果
直接在接口种的方法上面写上需要的返回值,Mybatis会自动进行封装。
需要注意的是只支持Boolean、Integer、Long这三种。
/**
* 添加用户
* @param user 一个用户实体信息封装类
* @return 是否插入成功
*/
boolean insertUser(User user);
/**
* 修改用户
* @param user
* @return 是否修改成功
*/
boolean updateUser(User user);
/**
* 删除用户
* @param id 要删除用户的ID
* @return 删除了多少行
*/
int deleteUser(int id);
Mysql获取自增主键的值
只用增加两个属性就行了。
以下是配置文件
<insert id="insertUser" parameterType="com.modevil.domain.User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user(userName, sex, address) VALUES(#{userName}, #{sex}, #{address});
</insert>
增加了两个属性:
- useGeneratedKeys:告诉Mybatis使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键
- keyProperty:指定对应实体类的属性
查
1、返回一个封装好的对象
/**
* 通过ID查询用户
* @param id 用户的ID
* @return
*/
User getUserById(int id);
<select id="getUserById" resultType="com.modevil.domain.User">
SELECT * FROM user WHERE id=#{id}
</select>
其中,resultType应为要返回的对象的全类名
2、返回封装好的对象的列表
/**
* 查询所有用户
* @return 所有用户信息
*/
List<User> getAllUser();
<select id="getAllUser" resultType="com.modevil.domain.User">
SELECT * FROM user
</select>
和第一个并没有太多的区别,resultType中的值为列表中的对象的类型。
3、将返回的数据封装为Map
/**
* 获取指定用户的部分信息
* @param id 用户Id
* @return 用户信息封装成的Map对象
*/
Map<String, Object> getPartMessageById(int id);
<select id="getPartMessageById" resultType="map">
SELECT id, userName, sex FROM user WHERE id=#{id}
</select>
查询数据的时候不一定每次都是返回一个对象,也可以将数据封装为一个Map。
其中,查询出来的结果是一条记录,Map的Key为列名,Value为值。
最后就是resultType中写map就可以的原因是mybatis已经给我们常用的一些数据起了别名。当然,直接写java.util.Map
也是可以的。
4、将返回的多个对象封装为一个map
/**
* 根据名字进行模糊查询
* @param name 名字中包含的字段
* @return 用户列表
*/
@MapKey("userName")
Map<String, User> getUsersByName(String name);
<!-- Map<String, User> getUsersByName(String name);-->
<select id="getUsersByName" resultType="com.modevil.domain.User">
SELECT * FROM user WHERE userName LIKE #{name}
</select>
在这个中resultType的值为Map中Value的类型,然后还需要在方法上面使用注解@MapKey("")
指定Map的Key是那一列,不然会报错。
5、一对一、多对一
如果一个对象中引用了另一个对象,在查询这个对象的时候,想把与其相关联的对象一起查出来。可以使用连接查询,或者是分布查询,在这种情况下就需要用resultMap来映射了。
关联查询
/**
* 通过Id查询用户,并一起获得其角色的信息
* @param id 用户Id
* @return
*/
User getUserWithRoleById(int id);
<resultMap id="MyUser1" type="com.modevil.domain.User">
<id column="id" property="id"/>
<result column="userName" property="userName"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<result column="roleId" property="role.id"/>
<result column="roleName" property="role.roleName"/>
<result column="authority" property="role.authority"/>
</resultMap>
<resultMap id="MyUser2" type="com.modevil.domain.User">
<id column="id" property="id"/>
<result column="userName" property="userName"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<association property="role" javaType="com.modevil.domain.Role">
<id column="roleId" property="id"/>
<result column="roleName" property="roleName"/>
<result column="authority" property="authority"/>
</association>
</resultMap>
<select id="getUserWithRoleById" resultMap="MyUser1">
SELECT u.id, u.userName, u.sex, u.address, u.roleId, r.roleName, r.authority
FROM user u LEFT JOIN role r ON u.roleId = r.id WHERE u.id=#{id}
</select>
- resultMap:自定义的映射规则,id为其唯一的索引,type是其映射的对象的全类名
- id:对应数据库中的主键列,column对应列名,property对应属性
- result:对应数据库的其他列
- association 映射关联的对象,property属性名,javaType关联对象的全类名
- select:resultMap,对应自定义的resultMap的Id
在这种情况下
- 在resultMap中可以直接使用对象名.属性名来映射User中的Role属性。对应MyUser1
- 在resultMap中使用association来映射关联的对象,对应MyUser2
分步查询
顾名思义,这个就是将原本的一个查询语句分开,分成两个不同的查询语句来分别进行查询。先查询到除关联对象之外的所有属性,然后再进行一次查询,单独查关联对象的属性。
在这种情况下,关联对象也需要有一个自己的Mapper映射文件,去映射相应的查询方法。
/**
* 分步查询用户,及其对应的关联角色
* @param id
* @return
*/
User getUserWithRoleStepById(int id);
<resultMap id="MyUser3" type="com.modevil.domain.User">
<id column="id" property="id"/>
<result column="userName" property="userName"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<association column="roleId" property="role" select="com.modevil.dao.RoleDao.getRoleById"/>
</resultMap>
<select id="getUserWithRoleStepById" resultMap="MyUser3">
SELECT * FROM user WHERE id=#{id}
</select>
association的select属性对应根据Id查询role对象的方法的全类名。
6、一对多
和上面的情况类似,但是是一个对象和多个其他的对象相关联,也有级联查询和分步查询两种情况。
级联
/**
* 通过角色Id查询相应的数据,并一同查出来对应的User对象
* @param id
* @return
*/
Role getRoleWithUserById(int id);
<resultMap id="myRole1" type="com.modevil.domain.Role">
<id column="id" property="id"/>
<result column="roleName" property="roleName"/>
<result column="authority" property="authority"/>
<collection property="users" ofType="com.modevil.domain.User">
<id column="uid" property="id"/>
<result column="userName" property="userName"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</collection>
</resultMap>
<select id="getRoleWithUserById" resultMap="myRole1">
SELECT r.id, r.roleName, r.authority, u.id uid, u.userName, u.sex, u.address
FROM role r LEFT JOIN user u ON r.ID = u.roleId WHERE r.id=#{id}
</select>
其中collection的属性property对应集合的属性名,ofType对应集合中元素的类型
分步
/**
* 分步的
* @param id
* @return
*/
Role getRoleWithUserStepById(int id);
<resultMap id="myRole2" type="com.modevil.domain.Role">
<id column="id" property="id"/>
<result column="roleName" property="roleName"/>
<result column="authority" property="authority"/>
<collection property="users" column="{roleId=id}" select="com.modevil.dao.UserDao.getUsersByRoleId"/>
</resultMap>
<select id="getRoleWithUserStepById" resultMap="myRole2">
SELECT * FROM role WHERE id=#{id}
</select>
其中collection的属性select对应根据roleId查询user方法的全类名。
鉴别器
使用鉴别器可以根据不同值使用不同的映射方法。
/**
* 使用鉴别器获取数据
* @param id
* @return
*/
User getUserSpecialById(int id);
<resultMap id="MyUser4" type="com.modevil.domain.User">
<id column="id" property="id"/>
<result column="userName" property="userName"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<discriminator javaType="String" column="sex">
<case value="男" resultType="com.modevil.domain.User">
<association column="roleId" property="role" select="com.modevil.dao.RoleDao.getRoleById"/>
</case>
<case value="女" resultType="com.modevil.domain.User">
</case>
</discriminator>
</resultMap>
<select id="getUserSpecialById" resultMap="MyUser4">
SELECT * FROM user WHERE id=#{id}
</select>
鉴别器和Java中的switch有点类似。
discriminator 参数:javaType指定判断的数据的类型,column数据的列
case 参数:value指定值为当前情况下的处理,resultType处理的结果的类型
输入参数
只有一个基本数据类型
在输入只有一个参数的情况下,Mybaits是不进行特殊处理的,不管sql语句的#{}中是什么,都可以成功执行。
传入一个对象作为参数
在这种情况下,我们可以直接使用#{属性名}来获取值。
传入多个参数
在这种情况下,MyBatis会对数据进行特殊处理,将参数封装成一个map;具体是怎么进行的可以去看尚硅谷的课程,讲的挺清楚的。
在这种情况下,我们可以使用索引或者是paramN(N为索引值)来获取,具体形式如下:#{N},#{paramN}。
这样获取一旦数据多了起来之后,容易混淆,可以在方法的参数前面加上注解@Param(“name”),这样在获取参数的时候就可以使用#{name}开获取数据了。
传入参数类型为Map
在传入参数类型为Map的情况下,可以直接使用#{Key}来获取值。
传入数据为Collection对象或者是数组
在这种情况下可以使用collection、list、array等来获取对象。
#{}与${}
相同之处:这两个都可以获取到值
不同之处:
#{}:是以预编译的形式,将参数设置到sql语句中;可以防止sql注入。
$ {}:取出的值直接拼装在sql语句中;会有安全问题。但是在原生jdbc不支持占位符的地方我们就可以使用${}进行取值。
最后就是#{}支持一些更高级的用法来对参数进行设置。
其他
还有缓存、懒加载等等配置,想了解的可以自己去看官方文档。
最后,如果有什么问题还请指正。
参考文档
- Mybatis的官方文档
- 尚硅谷的Mybatis教程