一、MyBatis事务
在创建sqlsession对象时传一个参数进去 true时 得到的SqlSession的事务自动提交时开启的SqlSession sqlSession = ``**build.openSession(**``**true**``**); **``(开发时用的少)
二、动态sql
1、 标签
在映射配置文件中这样写
<select id="findUserByCondition" resultType="com.yixuexi.entity.User" parameterType="com.yixuexi.entity.User">select * from user where 1 = 1 // 使用if标签 where 1=1不能省略<if test="name != null">and name = #{name}</if></select>
- 这里面的if 并且的关系是and 或者的关系是or
- 其实就是sql语句的拼接 在select语句后面 加个if就是拼接上if里面的内容
- 如果有多个条件 可以添加多个if
多个if都会执行select * from user where 1 = 1<if test="name != null">and name = #{name}</if><if test="password != null">and password = #{password}</if>
2、where标签
- 使用where标签可以省略 where 1 = 1
- 就是在 if标签外面套一层 where包裹起来
<select id="findUserByCondition" resultType="com.yixuexi.entity.User" parameterType="com.yixuexi.entity.User">select * from user<where><if test="name != null">and name = #{name}</if><if test="password != null">and password = #{password}</if></where></select>
3、foreach标签
```xml
---<a name="BE8gI"></a># 三、多表查询<a name="983ce102"></a>## 1、一对一的数据库查询<a name="GvXEy"></a>### 1、创建Account子类的方式 (不常用)`SQL`语句是这样的 (一个用户对一个账户)```sqlSELECTa.* , u.name AS NAME ,u.password AS PASSWORDFROMaccount aJOINUSER uONa.uid = u.id
- 此时mybatis需要准备好两张表 一张Account表 和 一张继承Account的表 继承的表里面有需要查出来的别的字段
- AccountUser子表 需要重写toString() 并且重写时,调用父类的toString() super.toString()
- 然后在AccountDao接口中创建一个方法
List``**<AccountUser**``> findAllAccountUser();- 返回值需是Account的子类,因为子类中有父类没有的属性 name 和 password
然后在映射文件中写sql语句
<select id="findAllAccountUser" resultType="AccountUser"><!--因为这里再主配置文件中配置了typeAliases所以直接写类名即可-->selecta.* , u.name ,u.passwordfromaccount ajoinuser uona.uid = u.id</select>
这里的数据库列名需要和实体类中的属性名一致,所以再创建子类的时候 属性名要写好
2、从表中有实体引用(常用)
1) 从表实体类中应该含一个主表实体的包对象引用
public class Account {private Integer id;private Integer uid;private Double money;//从表实体类中应该有一个主表的对象private User user;}
student学生表 引用了外键 class的id 班级表 那么说 student就是从表 class就是主表
2) SQL语句
selecta.*,u.id,u.name,u.passwordfromaccount ajoinuser uona.uid = u.id
3) 因为Account(子表)表中有一个主表的对象,那么再查询结果封装的时候是 没办法把User封装进去的,需要这样设置
<!--定义一个能封装account和user的resultMap--><resultMap id="accountUserMap" type="Account"><!--定义主键字段--><id property="id" column="id"></id><!--定义非主键字段--><result property="uid" column="uid"></result><result property="money" column="money"></result><!--一对一的关系映射:配置user的内容--><!--property:该实体类中的哪个对应关系的主表属性--><!--column:通过哪一个 字段进行获取的--><!--javaType:最后的结果封装到哪个类 正常写法是com.xxx.xx 用了TypeAlia..所以直接类名--><association property="user" column="uid" javaType="User"><!--在里面写User的属性和数据库对应起来--><id property="id" column="id"></id><result property="name" column="name"></result><result property="password" column="password"></result></association></resultMap>
4) sql语句原封不动的写就行
<select id="findAll" resultMap="**accountUserMap**">这里写上resultMap起的id名
2、一对多(一个用户有多个账户)
- 账户表的外键引用了用户表的主键,那么说账户表是从表,用户表示主表
- 一对多关系映射:主表实体中应该包含从表实体的集合引用
1、UserDao接口中的方法
List<User> findAll();
2、User实体类中的属性
public class User {private Integer id;private String name;private String password;//一对多关系映射:主表实体中应该包含从表实体的集合引用private List<Account> accounts;}
3、SQL语句
```sql select u.*,a.id as aid ,a.uid,a.money from user u left join account a on u.id = a.uid
因为有两个id所以给account表中的id起一个别名
<a name="34be61b6"></a>### 4、在映射配置文件中写对应关系```xml<!--定义User的resultMap 一对多查询--><!--id 随便起一个名字 type:类型仍然是一个User 配置了别名所以直接写类名--><resultMap id="UserAccountMap" type="User"><id property="id" column="id"></id><result property="name" column="name"></result><result property="password" column="password"></result><!--配置user对象中accounts集合的映射--><!--property:User对象的Account属性名--><!--ofType:集合中元素的类型(用了别名 不然要写权限定类名)--><!--一对多需要用 collection标签 --><collection property="accounts" ofType="Account"><id property="id" column="aid"></id><result property="uid" column="uid"></result><result property="money" column="money"></result></collection></resultMap>

3、多对多
多对多,三张表,关系表两个外键
示例:用户和角色
- 一个用户有多个角色
- 一个角色可以赋予多个用户
各自包含对方一个集合引用
- 当我们查询用户是,可以同时得到用户所包含的角色信息
- 当我们查询角色是,可以同时得到角色的所赋予的用户信息
1、SQL语句
查询身份并且显示对应的用户信息SELECTu.*,r.id AS role_id,r.role_name,r.role_descFROMUSER uJOINuser_role ur #连接关系表 条件是用户表的id等于关系表的uidONu.id = ur.uidJOINrole r ##连接身份表 条件是身份表的id等于关系表的ridONr.id = ur.rid数据库里面的id会有重复 所以要起一个别名,不过不要忘了配置文件的cloumn属性也改成别名
2、在RoleDao中创建一个方法
public interface RoleDao {/*** 查询所有角色* @return*/List<Role> findAll();}
3、Role实体类中的属性是这样的
public class Role implements Serializable {private Integer roleId;private String roleName;private String roleDesc;//多对多的关系映射,一个角色可以赋予多个用户private List<User> users;}
4、在RoleDaoMapper.xml文件中配置一下对应关系
<!--id就是起个名字 type:是什么类型,(全限定类名,但是又typeAlia)--><resultMap id="roleUserMap" type="Role"><!--配置主键 properties:类中的属性 column:数据库中的字段--><id property="roleId" column="role_id"></id><result property="roleName" column="role_name"></result><result property="roleDesc" column="role_desc"></result><!--配置role对象中的users集合映射关系--><!--properties:写要配置哪个属性名--><!--ofType:集合里面是什么数据类型(全限定类名 …)--><collection property="users" ofType="User" ><id property="id" column="id"></id><result property="name" column="name"></result><result property="password" column="password"></result></collection></resultMap>
5、编写测试类
RoleDao mapper = session.getMapper(RoleDao.class);List<Role> all = mapper.findAll();for (Role role : all) {System.out.print(role);System.out.println(role.getUsers());}
- 在循环的时候调用一下
role.getUsers(); - 或者直接把users重写进
toString()// 这样会直接输出 list集合的toString()而哪个List集合的toString()已经重写
