SqlMapConfig.xml配置文件

  • SqlMapConfig.xml中配置的内容和顺序如下:
  • properties(属性)
  • settings(全局配置参数)
  • typeAliases(类型别名)
  • typeHandlers(类型处理器)
  • objectFactory(对象工厂)
  • plugins(插件)
  • environments(环境集合属性对象)
  • environment(环境子属性对象)
  • transactionManager(事务管理)
  • dataSource(数据源)
  • mappers(映射器)

注意:配置文件的标签顺序需严格安装要求.


properties

原配置中: 
 
这部分可以有另外的使用方式: 
在同目录下新建一个properties的配置文件 
内容如下:

  1. jdbc.driver=com.mysql.jdbc.Driver
  2. jdbc.url=jdbc:mysql:///mybatis
  3. jdbc.username=root
  4. jdbc.password=

然后配置文件需修改为:

  1. <configuration>
  2. <!-- 配置properties
  3. 可以在标签内部配置连接数据库的信息。也可以通过属性引用外部配置文件信息
  4. resource属性: 常用的
  5. 用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下。
  6. url属性:
  7. 是要求按照Url的写法来写地址
  8. URL:Uniform Resource Locator 统一资源定位符。它是可以唯一标识一个资源的位置。
  9. 它的写法:
  10. http://localhost:8080/mybatisserver/demo1Servlet
  11. 协议 主机 端口 URI
  12. URI:Uniform Resource Identifier 统一资源标识符。它是在应用中可以唯一定位一个资源的。
  13. -->
  14. <properties resource="jdbcconfig.properties"></properties>
  15. <!--配置环境-->
  16. <environments default="mysql">
  17. <!-- 配置mysql的环境-->
  18. <environment id="mysql">
  19. <!-- 配置事务 -->
  20. <transactionManager type="JDBC"></transactionManager>
  21. <!--配置连接池-->
  22. <dataSource type="POOLED">
  23. <!--当使用外部配置文件是需要用${}引用-->
  24. <property name="driver" value="${jdbc.driver}"></property>
  25. <property name="url" value="${jdbc.url}"></property>
  26. <property name="username" value="${jdbc.username}"></property>
  27. <property name="password" value="${jdbc.password}"></property>
  28. </dataSource>
  29. </environment>
  30. </environments>

注意: MyBatis 将按照下面的顺序来加载属性:

  • 使用 properties 元素加载的外部属性文件优先级最高。
  • 然后会读取properties 元素中resource加载的属性,它会覆盖已读取的同名属性。

typeAliases(类型别名)

  1. </properties>
  2. <typeAliases>
  3. <!--用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
  4. <package name="com.it.domain"></package>
  5. </typeAliases>

 
不区分大小写 

mappers(映射器)

原配置信息:

重新配置后:

  1. <mappers>
  2. <!-- package标签是用于指定dao接口所在的包,当指定了之后就不需要在写mapper以及resource或者class了 -->
  3. <package name="com.it.dao"></package>
  4. </mappers>

此配置的前提是:要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

连接池与事务

type=”POOLED”:MyBatis会创建PooledDataSource实例 

结论:它是从池中获取一个连接来用。 
底层:PooledDataSource.java

总结:最后我们可以发现,真正连接打开的时间点,只是在我们执行SQL语句时,才会进行。其实这样做我们也可以进一步发现,数据库连接是我们最为宝贵的资源,只有在要用到的时候,才去获取并打开连接,当我们用完了就再立即将数据库连接归还到连接池中。 所以我们使用连接池的技术会节省连接资源。


面试题 
为什么MyBatis连接池要设计为有一个空闲连接列表和一个活动连接列表?

  • 1:从连接池的设计看,这两个连接列表都是必需的,加起来等于是连接池能用的最大连接数。
    • 2:当有新的连接请求时,有从空闲连接列表中选择一个可用的连接,如果这个连接可以正常执行,转移到活动连接列表。
    • 3:新建连接比较耗时,所以一开始就新建好一堆连接,这些连接没有被使用的时候就在空闲列表里。
    • 4:当要使用的时候,就从空闲列表里拿一个,放到活动列表里。

次: 
一:什么是事务? 

二:事务的四大特性ACID? 

三:不考虑隔离性会产生的3个问题?

  1. 脏读(针对未提交数据)如果一个事务中对数据进行了更新,但事务还没有提交,另一个事务可以“看到”该事务没有提交的更新结果,这样造成的问题就是,如果第一个事务回滚,那么,第二个事务在此之前所“看到”的数据就是一笔脏数据。
    1. 不可重复读(针对其他提交前后,读取数据本身的对比)不可重复读取是指同一个事务在整个事务过程中对同一笔数据进行读取,每次读取结果都不同。如果事务1在事务2的更新操作之前读取一次数据,在事务2的更新操作之后再读取同一笔数据一次,两次结果是不同的
    2. 幻读(针对其他提交前后,读取数据条数的对比) 幻读是指同样一笔查询在整个事务过程中多次执行后,查询所得的结果集是不一样的。幻读针对的是多笔记录。如果事务1在事务2的新增操作之前读取一次数据,在事务2的新增操作之后再读取同一笔数据,取得的结果集是不同的,幻读发生。
    3. 不可重复读和幻读比较: 两者有些相似,但是前者针对的是update或delete,后者针对的insert。

四:解决办法:四种隔离级别?

1、Serializable (串行化):最严格的级别,事务串行执行,资源消耗最大; 
2、REPEATABLE READ(重复读) :保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读”和“不可重复读”的情况,但不能避免“幻读”,但是带来了更多的性能损失。(mysql的默认隔离级别) 
3、READ COMMITTED (读已提交):大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读”,但不能避免“幻读”和“不可重复读”。该级别适用于大多数系统。(oracle的默认隔离级别) 
4、Read Uncommitted(读未提交) :事务中的修改,即使没有提交,其他事务也可以看得到,会导致“脏读”、“幻读”和“不可重复读取”。

总结:如果设置此时事务就设置为自动提交了,同样可以实现CUD操作时记录的保存。虽然这也是一种方式,但就编程而言,设置为自动提交方式为false再根据情况决定是否进行提交,这种方式更常用。因为我们可以根据业务情况来决定业务是否进行提交。如果设置自动提交,如果当前操作有误,事务很难设置回滚了。 只有设置为手动提交,我们才能更好的控制事务。


Mybatis映射文件的SQL深入

动态SQL之标签

第一步:UserDao.xml中配置

  1. <!--根据条件查询-->
  2. <select id="findByCondition" parameterType="user" resultMap="userMap">
  3. select * from user where 1=1
  4. <if test="userName != null">
  5. and username = #{userName}
  6. </if>
  7. <if test="userSex != null">
  8. and sex = #{userSex}
  9. </if>
  10. </select>

第二步:UserDao.java中配置 
List<User> findByCondition(User user);

第三步:MybatisTest.java中配置

  1. /**
  2. * 测试根据查询条件查询
  3. */
  4. @Test
  5. public void testFindByCondition(){
  6. User user = new User();
  7. user.setUserName("老王");
  8. //user.setUserSex("女");
  9. //5.执行查询一个方法
  10. List<User> users = userDao.findByCondition(user);
  11. for(User u : users){
  12. System.out.println(u);
  13. }
  14. }

注意:标签的test属性中写的是对象的属性名,如果是包装类的对象要使用OGNL表达式的写法。 
另外要注意where 1=1 的作用~ !

动态SQL之标签

UserDao.xml

  1. <!--where标签的使用(省略where 1=1)-->
  2. <select id="findByCondition" parameterType="user" resultMap="userMap">
  3. select * from user
  4. <where>
  5. <if test="userName != null">
  6. and username = #{userName}
  7. </if>
  8. <if test="userSex != null">
  9. and sex = #{userSex}
  10. </if>
  11. </where>
  12. </select>

<where />可以自动处理第一个and


动态SQL标签之标签

第一步:QueryVo.java

  1. public class QueryVo {
  2. private User user;
  3. private List<Integer> ids = new ArrayList<Integer>();

第二步:UserDao.xml

  1. <!--foreach标签的使用-->
  2. <select id="findInIds" parameterType="queryVo" resultMap="userMap">
  3. select * from user
  4. <where>
  5. <if test="ids != null and ids.size()>0">
  6. <foreach collection="ids" open=" and id in (" close=")" item="uid" separator=",">
  7. #{uid}
  8. </foreach>
  9. </if>
  10. </where>
  11. </select>

这里: 
SQL语句: select 字段from user where id in (?) 
<foreach>标签用于遍历集合,它的属性: 
collection:代表要遍历的集合元素,注意编写时不要写#{} 
open:代表语句的开始部分 
close:代表结束部分 
item:代表遍历集合的每个元素,生成的变量名 
sperator:代表分隔符

第三步:UserDao.java 
List<User> findInIds(QueryVo queryVo);

第四步:MybatisTest.java

  1. /**
  2. * 测试嵌套子查询forEach
  3. */
  4. @Test
  5. public void testFindInIds(){
  6. QueryVo queryVo = new QueryVo();
  7. List<Integer> ids = new ArrayList<Integer>();
  8. ids.add();
  9. ids.add();
  10. ids.add();
  11. ids.add();
  12. queryVo.setIds(ids);
  13. //5.执行查询一个方法
  14. List<User> users = userDao.findInIds(queryVo);
  15. for(User u : users){
  16. System.out.println(u);
  17. }
  18. }

Mybatis中简化编写的SQL片段

Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。 
我们先到UserDao.xml文件中使用标签,定义出公共部分,如下:

  1. <sql id="defaultUser">
  2. select * from user
  3. </sql>
  4. <!--foreach标签的使用-->
  5. <select id="findInIds" parameterType="queryVo" resultMap="userMap">
  6. <!--select * from user-->
  7. <include refid="defaultUser"></include>
  8. <where>
  9. <if test="ids != null and ids.size()>0">
  10. <foreach collection="ids" open=" and id in (" close=")" item="uid" separator=",">
  11. #{uid}
  12. </foreach>
  13. </if>
  14. </where>
  15. </select>

其中标签的refid属性的值就是 标签定义id的取值。 
注意:如果引用其它mapper.xml的sql片段,则在引用时需要加上namespace,如下: 
<include refid="namespace.sql片段”/> 
意思为当片段不是本文件的,需要用真实路径引用,如: 
<include refid="com.it.dao.mappers.defaultUser"></include>


Mybatis 的多表关联查询

本次案例主要以最为简单的用户和账户的模型来分析Mybatis 多表关系。用户为User 表,账户为Account 表。一个用户(User)可以有多个账户(Account)。具体关系如下: 

【创建表】【添加数据】

  1. DROP TABLE IF EXISTS `account`;
  2. CREATE TABLE `account` (
  3. `ID` INT(11) NOT NULL COMMENT '编号',
  4. `UID` INT(11) DEFAULT NULL COMMENT '用户编号',
  5. `MONEY` DOUBLE DEFAULT NULL COMMENT '金额',
  6. PRIMARY KEY (`ID`),
  7. KEY `FK_Reference_8` (`UID`),
  8. CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
  9. ) ENGINE=INNODB DEFAULT CHARSET=utf8;
  10. INSERT INTO `account`(`ID`,`UID`,`MONEY`) VALUES (1,46,1000),(2,45,1000),(3,46,2000);

Mybatis维护一对多关系

第三步:创建Account.java

  1. public class Account implements Serializable{
  2. private Integer id;
  3. private Integer uid;
  4. private Double money;
  5. // 省略set、get方法
  6. }

第四步:创建AccountDao.java

  1. /**
  2. * 用户的持久层接口
  3. */
  4. public interface AccountDao {
  5. /**
  6. * 查询所有用户
  7. * @return
  8. */
  9. List<Account> findAll();
  10. /**
  11. * 根据id查询用户信息
  12. * @param id
  13. * @return
  14. */
  15. Account findById(Integer id);
  16. }

第五步:创建AccountDao.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.it.dao.AccountDao">
  6. <!-- 查询所有 -->
  7. <select id="findAll" resultType="com.it.domain.Account">
  8. select * from account;
  9. </select>
  10. <!-- 根据id查询用户 -->
  11. <select id="findById" parameterType="INT" resultType="com.it.domain.Account">
  12. select * from account where id = #{uid}
  13. </select>
  14. </mapper>

第六步:编写测试类MybatisTest.xml

  1. public class MybatisTest {
  2. private InputStream in;
  3. private SqlSession sqlSession;
  4. private UserDao userDao;
  5. private AccountDao accountDao;
  6. @Before//用于在测试方法执行之前执行
  7. public void init()throws Exception{
  8. //1.读取配置文件,生成字节输入流
  9. in = Resources.getResourceAsStream("SqlMapConfig.xml");
  10. //2.获取SqlSessionFactory
  11. SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
  12. //3.获取SqlSession对象
  13. sqlSession = factory.openSession();
  14. //4.获取dao的代理对象
  15. userDao = sqlSession.getMapper(UserDao.class);
  16. accountDao = sqlSession.getMapper(AccountDao.class);
  17. }
  18. }

测试查询所有。

  1. /**
  2. * 查询所有账户
  3. */
  4. @Test
  5. public void testFindAllAccount(){
  6. //5.执行查询所有方法
  7. List<Account> list = accountDao.findAll();
  8. for(Account account : list){
  9. System.out.println(account);
  10. }
  11. }

这里别忘记配置:在SqlMapConfig.xml中

  1. <mappers>
  2. <!--<mapper resource="com/it/dao/UserDao.xml"></mapper>-->
  3. <!--<mapper resource="com/it/dao/AccountDao.xml"></mapper>-->
  4. <package name="com.it.dao"></package>
  5. </mappers>

一对多查询,查询用户,同时查询账号的集合

需求:查询所有用户信息及用户关联的账户信息。 
分析:用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息查询出来,只不过没有信息的字段用null表示,我们想到了左外连接查询比较合适。 
第一步: 
Sql语句: 
SELECT u.*, a.id as aid, a.uid, a.money FROM user u LEFT JOIN account a ON u.id = a.uid 

第二步:修改User.java对象

  1. public class User implements Serializable {
  2. private Integer id;
  3. private String username;
  4. private String address;
  5. private String sex;
  6. private Date birthday;
  7. private List<Account> accounts;
  8. public List<Account> getAccounts() {
  9. return accounts;
  10. }
  11. public void setAccounts(List<Account> accounts) {
  12. this.accounts = accounts;
  13. }
  14. }

重写toString的方法

  1. @Override
  2. public String toString() {
  3. return "User{" +
  4. "id=" + id +
  5. ", username='" + username + '\'' +
  6. ", address='" + address + '\'' +
  7. ", sex='" + sex + '\'' +
  8. ", birthday=" + birthday +
  9. ", accounts=" + accounts +
  10. '}';
  11. }

第三步:UserDao.java接口中加入查询方法 
在UserDao接口中加入查询方法:public List findUserAccountList();

  1. /**
  2. * 根据用户账号的信息
  3. * @param
  4. * @return
  5. */
  6. List<User> findUserAccountList();

第四步:修改UserDao.xml映射文件

  1. <!--定义用户和账号的查询-->
  2. <resultMap id="userMap" type="user">
  3. <id property="id" column="id"></id>
  4. <result property="username" column="username"></result>
  5. <result property="address" column="address"></result>
  6. <result property="sex" column="sex"></result>
  7. <result property="birthday" column="birthday"></result>
  8. <collection property="accounts" ofType="account">
  9. <id property="id" column="aid"></id>
  10. <result property="uid" column="uid"></result>
  11. <result property="money" column="money"></result>
  12. </collection>
  13. </resultMap>
  14. <!-- 根据用户和账号的信息 -->
  15. <select id="findUserAccountList" resultMap="userMap">
  16. SELECT u.*, a.id as aid, a.uid, a.money FROM user u LEFT JOIN account a ON u.id = a.uid
  17. </select>

这里: 
collection部分定义了用户关联的账户信息。表示关联查询结果集 
property="accounts":关联查询的结果集存储在User对象的上哪个属性。 
ofType="account":指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名,即com.it.domain.Account。 
及的意义同一对一查询。

第五步:在测试类MybatisTest.java中添加:

  1. /**
  2. * 查询所有用户和账号信息
  3. */
  4. @Test
  5. public void testFindUserAccountList(){
  6. //5.执行查询所有方法
  7. List<User> list = userDao.findUserAccountList();
  8. for(User user : list){
  9. System.out.println(user);
  10. }
  11. }

Mybatis维护多对多关系

用户与角色的多对多关系模型如下: 

在 MySQL 数据库中添加角色表,用户角色的中间表。 
角色表 

角色用户关联表(中间表) 

创建表:导入数据

  1. DROP TABLE IF EXISTS `role`;
  2. CREATE TABLE `role` (
  3. `ID` int() NOT NULL COMMENT '编号',
  4. `ROLE_NAME` varchar() default NULL COMMENT '角色名称',
  5. `ROLE_DESC` varchar() default NULL COMMENT '角色描述',
  6. PRIMARY KEY (`ID`)
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  8. insert into `role`(`ID`,`ROLE_NAME`,`ROLE_DESC`) values (,'院长','管理整个学院'),(,'总裁','管理整个公司'),(,'校长','管理整个学校');
  9. DROP TABLE IF EXISTS `user_role`;
  10. CREATE TABLE `user_role` (
  11. `UID` int() NOT NULL COMMENT '用户编号',
  12. `RID` int() NOT NULL COMMENT '角色编号',
  13. PRIMARY KEY (`UID`,`RID`),
  14. KEY `FK_Reference_10` (`RID`),
  15. CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `role` (`ID`),
  16. CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
  17. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  18. insert into `user_role`(`UID`,`RID`) values (,),(,),(,);

第三步:创建Role.java 
这里注意,我们使用属性和数据库字段并不相同

  1. public class Role implements Serializable {
  2. private Integer roleId;
  3. private String roleName;
  4. private String roleDesc;
  5. }

第四步:创建RoleDao.java

  1. /**
  2. * 角色的持久层接口
  3. */
  4. public interface RoleDao {
  5. /**
  6. * 查询所有角色
  7. * @return
  8. */
  9. List<Role> findAll();
  10. /**
  11. * 根据id查询角色信息
  12. * @param id
  13. * @return
  14. */
  15. Role findById(Integer id);
  16. }

第五步:创建RoleDao.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.it.dao.RoleDao">
  6. <resultMap id="roleMap" type="com.it.domain.Role">
  7. <id property="roleId" column="rid"></id>
  8. <result property="roleName" column="role_name"></result>
  9. <result property="roleDesc" column="role_desc"></result>
  10. </resultMap>
  11. <!-- 查询所有-->
  12. <select id="findAll" resultMap="roleMap">
  13. select * from role;
  14. </select>
  15. <!-- 根据id查询用户 -->
  16. <select id="findById" parameterType="INT" resultMap="roleMap">
  17. select * from role where id = #{uid}
  18. </select>

第六步:编写测试类MybatisTest.java

  1. /**
  2. * 测试mybatis的crud操作
  3. */
  4. public class MybatisTest {
  5. private InputStream in;
  6. private SqlSession sqlSession;
  7. private UserDao userDao;
  8. private RoleDao roleDao;
  9. @Before//用于在测试方法执行之前执行
  10. public void init()throws Exception{
  11. //1.读取配置文件,生成字节输入流
  12. in = Resources.getResourceAsStream("SqlMapConfig.xml");
  13. //2.获取SqlSessionFactory
  14. SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
  15. //3.获取SqlSession对象
  16. sqlSession = factory.openSession();
  17. //4.获取dao的代理对象
  18. userDao = sqlSession.getMapper(UserDao.class);
  19. roleDao = sqlSession.getMapper(RoleDao.class);
  20. }
  21. }

测试查询所有。

  1. /**
  2. * 测试查询所有角色
  3. */
  4. @Test
  5. public void testFindAllRole(){
  6. //5.执行查询所有方法
  7. List<Role> roles = roleDao.findAll();
  8. for(Role role : roles){
  9. System.out.println(role);
  10. }
  11. }

多对多查询,查询角色,同时关联用户

【需求】:查询所有角色,同时获取角色的所赋予的用户 

第一步:sql语句

SELECT u.*,r.id AS rid,r.role_name,r.role_desc FROM role r 
LEFT JOIN user_role ur ON r.ID = ur.rid 
LEFT JOIN USER u ON u.id = ur.uid 

第二步:修改Role.java 
我们加载的信息中不仅有角色信息,同时还要加载关联加载具有该角色的用户信息。因为一个角色,可以分配给多个用户,所以我们可以考虑在 Role 类中加入一个 List的属性,用于存放这个角色分配给了哪些用户对象。

  1. public class Role implements Serializable {
  2. private Integer roleId;
  3. private String roleName;
  4. private String roleDesc;
  5. private List<User> users = new ArrayList<User>();
  6. public List<User> getUsers() {
  7. return users;
  8. }
  9. public void setUsers(List<User> users) {
  10. this.users = users;
  11. }
  12. }

重写Role对象的toString方法。

  1. @Override
  2. public String toString() {
  3. return "Role{" +
  4. "roleId=" + roleId +
  5. ", roleName='" + roleName + '\'' +
  6. ", roleDesc='" + roleDesc + '\'' +
  7. ", users=" + users +
  8. '}';
  9. }

第三步:RoleDao.java

  1. /**
  2. * 查询所有角色信息,同时查询用户的信息
  3. * @param
  4. * @return
  5. */
  6. List<Role> findRoleUserList();

第四步:RoleDao.xml

  1. <resultMap id="roleMap" type="com.it.domain.Role">
  2. <id property="roleId" column="rid"></id>
  3. <result property="roleName" column="role_name"></result>
  4. <result property="roleDesc" column="role_desc"></result>
  5. <collection property="users" ofType="user">
  6. <id property="id" column="id"></id>
  7. <result property="username" column="username"></result>
  8. <result property="address" column="address"></result>
  9. <result property="sex" column="sex"></result>
  10. <result property="birthday" column="birthday"></result>
  11. </collection>
  12. </resultMap>
  13. <!-- 查询所有角色,同时查询所有用户 -->
  14. <select id="findRoleUserList" resultMap="roleMap">
  15. SELECT u.*,r.id AS rid,r.role_name,r.role_desc FROM role r
  16. LEFT JOIN user_role ur ON r.ID = ur.rid
  17. LEFT JOIN USER u ON u.id = ur.uid
  18. </select>

这里需注意:sql语句如果有换行,需要在sql的后面尽量加一个空格。

第五步:MybatisTest.java

  1. /**
  2. * 测试查询所有的角色
  3. */
  4. @Test
  5. public void testFindRoleUserList(){
  6. //5.执行查询所有方法
  7. List<Role> roles = roleDao.findRoleUserList();
  8. for(Role role : roles){
  9. System.out.println(role);
  10. }
  11. }

多对多查询,查询用户,同时关联角色

【需求】:查询所有用户,同时获取用户的所赋予的角色

第一步:sql语句

SELECT u.*,r.id AS rid,r.role_name,r.role_desc FROM USER u 
LEFT JOIN user_role ur ON u.ID = ur.uid 
LEFT JOIN role r ON r.id = ur.rid 

第二步:修改User.java

  1. public class User implements Serializable{
  2. private Integer id;
  3. private String username;
  4. private String address;
  5. private String sex;
  6. private Date birthday;
  7. private List<Role> roles = new ArrayList<Role>();
  8. public List<Role> getRoles() {
  9. return roles;
  10. }
  11. public void setRoles(List<Role> roles) {
  12. this.roles = roles;
  13. }
  14. }

重写User对象的toString方法。

  1. @Override
  2. public String toString() {
  3. return "User{" +
  4. "id=" + id +
  5. ", username='" + username + '\'' +
  6. ", address='" + address + '\'' +
  7. ", sex='" + sex + '\'' +
  8. ", birthday=" + birthday +
  9. ", roles=" + roles +
  10. '}';
  11. }

第三步:UserDao.java

  1. /**
  2. * 查询所有的用户,同时查询关联的角色信息
  3. * @param
  4. * @return
  5. */
  6. List<User> findUserRoleList();

第四步:UserDao.xml

  1. <resultMap id="userMap" type="user">
  2. <id property="id" column="id"></id>
  3. <result property="username" column="username"></result>
  4. <result property="address" column="address"></result>
  5. <result property="birthday" column="birthday"></result>
  6. <result property="sex" column="sex"></result>
  7. <collection property="roles" ofType="role">
  8. <id property="roleId" column="rid"></id>
  9. <result property="roleName" column="role_name"></result>
  10. <result property="roleDesc" column="role_desc"></result>
  11. </collection>
  12. </resultMap>
  13. <!-- 查询所有的用户,同时查询关联的角色信息 -->
  14. <select id="findUserRoleList" resultMap="userMap">
  15. SELECT u.*,r.id AS rid,r.role_name,r.role_desc FROM USER u
  16. LEFT JOIN user_role ur ON u.ID = ur.uid
  17. LEFT JOIN role r ON r.id = ur.rid
  18. </select>

这里需注意:sql语句如果有换行,需要在sql的后面尽量加一个空格。 
第五步:MybatisTest.java

  1. /**
  2. * 测试查询所有的用户
  3. */
  4. @Test
  5. public void testFindUserRoleList(){
  6. //5.执行查询所有方法
  7. List<User> users = userDao.findUserRoleList();
  8. for(User user : users){
  9. System.out.println(user);
  10. }
  11. }

Mybatis_two的更多相关文章

随机推荐

  1. 第一次react-native项目实践要点总结 good

    今天完成了我的第一个react-native项目的封包,当然其间各种环境各种坑,同时,成就感也是满满的.这里总结一下使用react-native的一些入门级重要点(不涉及环境).注意:阅读需要语法基础 ...

  2. 从源码角度看MySQL memcached plugin——1. 系统结构和引擎初始化

    本章尝试回答两个问题: 一.memcached plugin与MySQL的关系: 二.MySQL系统如何启动memcached plugin. 1. memcached plugin与MySQL的关系 ...

  3. FFmpeg来源简单分析:结构会员管理系统-AVClass

    ===================================================== FFmpeg章列表: [架构图] FFmpeg源码结构图 - 解码 FFmpeg源码结构图 ...

  4. Angular路由守卫 canActivate

    作用 canActivate 控制是否允许进入路由. canActivateChild 等同 canActivate,只不过针对是所有子路由. 关键代码 创建路由守卫 import { Injecta ...

  5. Mybatis常用操作 专题

    parameterType:即将传入的语句参数的完全限定类名和别名.这个属性是可选项的,因为MyBatis可以推断出传入语句的具体参数,因此不建议配置该属性flushCache:默认值为true,任何 ...

  6. WPF 动态绑定listview的列内容

    Binding binding = new Binding(); binding.Path = new PropertyPath("State"); listViewState.D ...

  7. C# IDisposable接口的使用

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  8. EF CodeFirst的步骤

    1 创建各个实体类 2 创建一个空数据模型,然后删除掉,为了引入Entity Framework和System.Data.Entity 3 为实体类增加标注 4 为实体增加导航属性 5 在App.co ...

  9. JS 中click和onclick的区别

    1.onclick是绑定事件,告诉浏览器在鼠标点击时候要做什么 2.click本身是方法,作用是触发onclick事件,只要执行了元素的click()方法,就会触发onclick事件

  10. WPF最大化避免覆盖任务栏

    原文:WPF最大化避免覆盖任务栏 WPF当窗体WindowStyle=”None”时,最大化会覆盖掉任务栏.如何解决这个问题呢? 我在Google里面搜到一篇文章,要用到Win32 API,通过让WP ...