一、MyBatis事务

在创建sqlsession对象时传一个参数进去 true时 得到的SqlSession的事务自动提交时开启的
SqlSession sqlSession = ``**build.openSession(**``**true**``**); **``(开发时用的少)

二、动态sql

动态SQL 官网

1、 标签

在映射配置文件中这样写

  1. <select id="findUserByCondition" resultType="com.yixuexi.entity.User" parameterType="com.yixuexi.entity.User">
  2. select * from user where 1 = 1 // 使用if标签 where 1=1不能省略
  3. <if test="name != null">
  4. and name = #{name}
  5. </if>
  6. </select>
  • 这里面的if 并且的关系是and 或者的关系是or
  • 其实就是sql语句的拼接 在select语句后面 加个if就是拼接上if里面的内容
  • 如果有多个条件 可以添加多个if
    1. select * from user where 1 = 1
    2. <if test="name != null">
    3. and name = #{name}
    4. </if>
    5. <if test="password != null">
    6. and password = #{password}
    7. </if>
    多个if都会执行

2、where标签

  • 使用where标签可以省略 where 1 = 1
  • 就是在 if标签外面套一层 where包裹起来
    1. <select id="findUserByCondition" resultType="com.yixuexi.entity.User" parameterType="com.yixuexi.entity.User">
    2. select * from user
    3. <where>
    4. <if test="name != null">
    5. and name = #{name}
    6. </if>
    7. <if test="password != null">
    8. and password = #{password}
    9. </if>
    10. </where>
    11. </select>

    3、foreach标签

    ```xml
  1. ---
  2. <a name="BE8gI"></a>
  3. # 三、多表查询
  4. <a name="983ce102"></a>
  5. ## 1、一对一的数据库查询
  6. <a name="GvXEy"></a>
  7. ### 1、创建Account子类的方式 (不常用)
  8. `SQL`语句是这样的 (一个用户对一个账户)
  9. ```sql
  10. SELECT
  11. a.* , u.name AS NAME ,u.password AS PASSWORD
  12. FROM
  13. account a
  14. JOIN
  15. USER u
  16. ON
  17. a.uid = u.id
  • 此时mybatis需要准备好两张表 一张Account表 和 一张继承Account的表 继承的表里面有需要查出来的别的字段
    • AccountUser子表 需要重写toString() 并且重写时,调用父类的toString() super.toString()
  • 然后在AccountDao接口中创建一个方法
    • List``**<AccountUser**``> findAllAccountUser();
    • 返回值需是Account的子类,因为子类中有父类没有的属性 name 和 password
  • 然后在映射文件中写sql语句

    1. <select id="findAllAccountUser" resultType="AccountUser">
    2. <!--因为这里再主配置文件中配置了typeAliases所以直接写类名即可-->
    3. select
    4. a.* , u.name ,u.password
    5. from
    6. account a
    7. join
    8. user u
    9. on
    10. a.uid = u.id
    11. </select>
  • 这里的数据库列名需要和实体类中的属性名一致,所以再创建子类的时候 属性名要写好

2、从表中有实体引用(常用)

1) 从表实体类中应该含一个主表实体的包对象引用

  1. public class Account {
  2. private Integer id;
  3. private Integer uid;
  4. private Double money;
  5. //从表实体类中应该有一个主表的对象
  6. private User user;
  7. }

student学生表 引用了外键 class的id 班级表 那么说 student就是从表 class就是主表

2) SQL语句

  1. select
  2. a.*,u.id,u.name,u.password
  3. from
  4. account a
  5. join
  6. user u
  7. on
  8. a.uid = u.id

3) 因为Account(子表)表中有一个主表的对象,那么再查询结果封装的时候是 没办法把User封装进去的,需要这样设置

  1. <!--定义一个能封装account和user的resultMap-->
  2. <resultMap id="accountUserMap" type="Account">
  3. <!--定义主键字段-->
  4. <id property="id" column="id"></id>
  5. <!--定义非主键字段-->
  6. <result property="uid" column="uid"></result>
  7. <result property="money" column="money"></result>
  8. <!--一对一的关系映射:配置user的内容-->
  9. <!--property:该实体类中的哪个对应关系的主表属性-->
  10. <!--column:通过哪一个 字段进行获取的-->
  11. <!--javaType:最后的结果封装到哪个类 正常写法是com.xxx.xx 用了TypeAlia..所以直接类名-->
  12. <association property="user" column="uid" javaType="User">
  13. <!--在里面写User的属性和数据库对应起来-->
  14. <id property="id" column="id"></id>
  15. <result property="name" column="name"></result>
  16. <result property="password" column="password"></result>
  17. </association>
  18. </resultMap>

4) sql语句原封不动的写就行

<select id="findAll" resultMap="**accountUserMap**">这里写上resultMap起的id名


2、一对多(一个用户有多个账户)

  • 账户表的外键引用了用户表的主键,那么说账户表是从表,用户表示主表
  • 一对多关系映射:主表实体中应该包含从表实体的集合引用

    1、UserDao接口中的方法

    1. List<User> findAll();

    2、User实体类中的属性

    1. public class User {
    2. private Integer id;
    3. private String name;
    4. private String password;
    5. //一对多关系映射:主表实体中应该包含从表实体的集合引用
    6. private List<Account> accounts;
    7. }

    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起一个别名

  1. <a name="34be61b6"></a>
  2. ### 4、在映射配置文件中写对应关系
  3. ```xml
  4. <!--定义User的resultMap 一对多查询-->
  5. <!--id 随便起一个名字 type:类型仍然是一个User 配置了别名所以直接写类名-->
  6. <resultMap id="UserAccountMap" type="User">
  7. <id property="id" column="id"></id>
  8. <result property="name" column="name"></result>
  9. <result property="password" column="password"></result>
  10. <!--配置user对象中accounts集合的映射-->
  11. <!--property:User对象的Account属性名-->
  12. <!--ofType:集合中元素的类型(用了别名 不然要写权限定类名)-->
  13. <!--一对多需要用 collection标签 -->
  14. <collection property="accounts" ofType="Account">
  15. <id property="id" column="aid"></id>
  16. <result property="uid" column="uid"></result>
  17. <result property="money" column="money"></result>
  18. </collection>
  19. </resultMap>

未命名图片.png

  • 为什么是column是aid 因为查询的有两个id 一个用户id 一个 账户id 为了区分在起了个别名
  • 同时 sql语句也要写上 a.id as aid

    5、编写测试类

3、多对多

多对多,三张表,关系表两个外键
示例:用户和角色

  • 一个用户有多个角色
  • 一个角色可以赋予多个用户

各自包含对方一个集合引用

  • 当我们查询用户是,可以同时得到用户所包含的角色信息
  • 当我们查询角色是,可以同时得到角色的所赋予的用户信息

1、SQL语句

  1. 查询身份并且显示对应的用户信息
  2. SELECT
  3. u.*,r.id AS role_id,r.role_name,r.role_desc
  4. FROM
  5. USER u
  6. JOIN
  7. user_role ur #连接关系表 条件是用户表的id等于关系表的uid
  8. ON
  9. u.id = ur.uid
  10. JOIN
  11. role r ##连接身份表 条件是身份表的id等于关系表的rid
  12. ON
  13. r.id = ur.rid
  14. 数据库里面的id会有重复 所以要起一个别名,不过不要忘了配置文件的cloumn属性也改成别名

2、在RoleDao中创建一个方法

  1. public interface RoleDao {
  2. /**
  3. * 查询所有角色
  4. * @return
  5. */
  6. List<Role> findAll();
  7. }

3、Role实体类中的属性是这样的

  1. public class Role implements Serializable {
  2. private Integer roleId;
  3. private String roleName;
  4. private String roleDesc;
  5. //多对多的关系映射,一个角色可以赋予多个用户
  6. private List<User> users;
  7. }

4、在RoleDaoMapper.xml文件中配置一下对应关系

  1. <!--id就是起个名字 type:是什么类型,(全限定类名,但是又typeAlia)-->
  2. <resultMap id="roleUserMap" type="Role">
  3. <!--配置主键 properties:类中的属性 column:数据库中的字段-->
  4. <id property="roleId" column="role_id"></id>
  5. <result property="roleName" column="role_name"></result>
  6. <result property="roleDesc" column="role_desc"></result>
  7. <!--配置role对象中的users集合映射关系-->
  8. <!--properties:写要配置哪个属性名-->
  9. <!--ofType:集合里面是什么数据类型(全限定类名 …)-->
  10. <collection property="users" ofType="User" >
  11. <id property="id" column="id"></id>
  12. <result property="name" column="name"></result>
  13. <result property="password" column="password"></result>
  14. </collection>
  15. </resultMap>

5、编写测试类

  1. RoleDao mapper = session.getMapper(RoleDao.class);
  2. List<Role> all = mapper.findAll();
  3. for (Role role : all) {
  4. System.out.print(role);
  5. System.out.println(role.getUsers());
  6. }
  • 在循环的时候调用一下role.getUsers();
  • 或者直接把users重写进toString() // 这样会直接输出 list集合的toString() 而哪个List集合的toString()已经重写