多表查询:
建数据库的表名字段名全部是小写,windows系统下对于大小写不敏感,但是在linux上对于大小写就是敏感的;
一对一:一篇博客对应着一个作者,博客表{一个作者User属性}使用assocation属性
一对多:一个作者对应着多篇博客,用户表{List<博客> blogs属性}使用collection属性
ResultMap和ResultType的区别:
1)字段映射不同:resultType适用于数据库字段名和实体类的名字是相同的,但是假设实体类的名字叫做username,但是数据库的名字是name,这时候数据库字段名和实体类的名字是不一样的,所以我们需要使用ResultMap,当我们对数据库表中的字段映射到一个对象里面的属性,MYSQL表中的字段名和类中字段名不一致的时候进行映射的处理;
2)多表查询不同:多表查询适用于ResultMap,resultType不能使用;
1)resultType表示数据库中返回的数据映射在JAVA中的程序中所对应的类型,只要定义类中的属性和数据库中的表的字段名称一致就没有任何问题,但是如果不一致,那么冲突的属性就无法获取到数据库查询的结果,比如说用户的属性在数据库中的名字是username,而在JAVA程序中的类名是name,此时通过MyBatis将数据传递给程序中的对象的时候,此时获取到的name属性就是null,此时就不能正确地获取到对应的属性值,为了解决数据库中的字段和类中的字段不匹配的问题,此时就需要使用到resultMap;
2)resultMap的使用方式就是在xml文件中设置
标签,它至少包含两个属性,一个是ID表示你这个resultMap标签的名字,还有一个是type属性,它表示映射到程序中类的类型,需要包含包名; 3)在ResultMap标签里面至少包含着两个子标签,一个是id标签,一个是result标签,前者表示,前者表示主键或者表示数据库中的普通的列,这两个标签也是至少设置两个属性,一个是column表示数据库中表的字段名,一个是property表示程序类中对应的属性名,如果只是在单表查询,只是设置不同的字段名的映射即可,但是如果是多表查询,必须将数据库中的字段和类中的所有属性生成映射关系
1)resultMap里面还是做的是数据库表中的属性到类中的字段的一个映射,有可能是类中的一个属性对应着表中的一个属性,或者是类中的一个属性对应着表中的多个字段;
2)如果多表联查中两个表对应的两个类属性是相同的,那么后面的表的字段的值将会被前一个表中的相同的字段值所覆盖,况且设置前缀尽量在后面的类中的一个属性进行设置;
指定别名的作用:通常给第二张表的相同字段指定别名
如果说进行连表查询的时候两张表有相同的字段,那么在你不指定别名的情况下,第二张表重复的字段将会被第一张表重复的字段属性所覆盖,如果多张表的两张表的字段全部不一样,那么此时设置前缀不会有任何问题
下面我们来进行演示一下一对一:
1)在上面我们已经完成了多表查询,现在我们在进行创建一张表,叫做blog表,博客表
我们既然要进行一对一的多表查询,一对一映射,因为一篇博客值对应着一个作者
2)设置前缀的作用:因为我们知道,在实际的工作环境中,我们的博客表和用户表很有可能是存在相同的字段名的,很有可能是说我们的User表里面,有一个唯一的用户身份标识叫做ID,还有一个唯一的博客身份标识也叫做ID,那么这时候我们进行连表查询的时候就会出现严重的问题,所以我们要进行设置一个别名,前缀是用来解决多张表中相同字段覆盖的问题
3)因为一篇博客对应着唯一的作者,所以我们在博客列表对应的Java代码中,我们要进行设置一个User属性,下面是我们的数据库建表操作和创建实体类,我们还要安装MyBatisX这个插件
create table blog( blogID int primary key auto_increment, userID int, title varchar(30), content varchar(30)); @Data public class Blog { int blogID; int userID; String title; String content; User user; }
- create table user(
- userID int primary key auto_increment,
- username varchar(100),
- password varchar(100));
- insert into user values(null,"张三","7777"),(null,"王五","123456"),(null,"李武","999");
- insert into blog values(null,1,"JAVA","好好学习");
- insert into blog values(null,1,"CPP","不想毕业");
- insert into blog values(null,2,"py","好好休息");
- insert into blog values(null,3,"c#","天天向上");
- insert into blog values(null,2,"jjjj","好好休息");
- insert into blog values(null,3,"王者荣耀","天天向上");
1)我们写的BlogController里面的代码:
@Controller public class BlogController { @Autowired BlogService blogService; @RequestMapping("/GetAll") @ResponseBody public ListGetAll() { return blogService.GetAll(); } }2)我们写的BlogService里面的代码:
@Service public class BlogService { @Autowired BlogMapper mapper; public ListGetAll() { return mapper.GetAll(); } }3)我们写的BlogMapper接口里面的代码和blogMapper.XML文件里面的代码:
这个是BlogMapper接口里面的代码: @Mapper public interface BlogMapper { List<Blog> GetAll(); } 这个是XML文件里面的代码: "1.0" encoding="UTF-8"?> mapper PUBLIC "-//mybatis.org//DTD com.example.demo.Mapper1 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.Mapper.BlogMapper"> <select id="GetAll" resultType="com.example.demo.Blog"> select * from blog left join user on user.userID=blog.userID; select> mapper>1)我们在这个XML文件里面我们用namespace指定了我们实现接口的位置换句话来说就是实现接口的路径;
2)我们用resultType表示了我们要返回的类型,换句话说就是我们数据库表对应的实体类的路径;
3)注意一下在整个XML文件里面,我们都没有进行指定User实体类的路径,因为在我们blog类中还有User这样的属性,由于XML文件中没有这样的指定位置,所以我们无法得到User对象,所以我们看到当我们使用浏览器进行访问的时候,我们无法得到user对象
4)所以我们使用resultType指定实体类的路径的方法是不行的,我们尝试用一下resultMap
标签的用法: 第一个字段property的参数指定的是我们blog表中要进行关联的属性
第二个字段resultMap,表示User表中的resultMap的位置:
第三个参数表示前缀,我们想要查询User对象的所有字段的属性都要加上前缀:
blogMapper.xml文件里面的代码: "1.0" encoding="UTF-8"?> mapper PUBLIC "-//mybatis.org//DTD com.example.demo.Mapper1 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.Mapper.BlogMapper"> <resultMap id="BaseMap" type="com.example.demo.Blog"> <id property="blogID" column="blogID">id> <result property="userID" column="userID">result> <result property="title" column="title">result> <result property="content" column="content">result> <association property="user" resultMap="com.example.demo.Mapper.UserMapper.BaseMapHH" columnPrefix="u_">association> resultMap> <select id="GetAll" resultMap="BaseMap"> select blog.*,user.userID as u_userID,user.classID as u_classID,user.password as u_password,user.username as u_username from blog left join user on user.userID=blog.userID; select> mapper>
我们写的UserMapper.xml里面的代码:
"1.0" encoding="UTF-8"?> mapper PUBLIC "-//mybatis.org//DTD com.example.demo.Mapper1 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.Mapper.UserMapper"> <resultMap id="BaseMapHH" type="com.example.demo.User"> <id column="userID" property="userID">id> <result column="classID" property="classID">result> <result column="username" property="username">result> <result column="password" property="password">result> resultMap> mapper>我们此时进行创建方法,我们进行返回的是一个List
集合,里面包含了若干个blog,里面都包含了唯一的作者,所以说我们是不能使用resultType会导致我们的自定义的对象没有值
1)resultMap:所以说我们一定要在我们所关联对象的XML文件里面建立一个resultMap,是不能指定一个resultType,所以说我们要存放管理属性的字典映射;
2)别忘了写前缀,如果说我们在进行多表查询的时候两张表出现了相同的字段,如果没设置前缀,那么查询的结果就是错误的,防止多张表出现相同字段查询问题;
现在我们使用一下一对多查询:
1)咱们说上面我们进行多表查询的时候,我们的一篇博客是对应着一个作者,这是一对一的关系,但是从另一个角度来说:我们的一个作者又是对应着多篇博客的,所以我们针对一对多来进行查询;
2)因为一个作者是对应着多篇博客的,所以我们要在user表里面加上一个字段List
>
@Setter @Getter @ToString public class User { private int ClassID; private int userID; private String username; private String password; Listlist; }我们可以先写一个SQL语句进行验证一下:
展示代码:
1)我们写的UserController里面的代码:
public class UserController { @Autowired UserService userService; @RequestMapping("/Get") @ResponseBody public ListGetAll() { return userService.GetAll(); } }2)咱们的UserService和UserMapper里面的代码如下:
@Service public class UserService { @Autowired private UserMapper mapper; public ListGetAll() { return mapper.GetAll(); } } @Mapper public interface UserMapper { ListGetAll(); }3)咱们的blogXML文件中的代码如下:
"1.0" encoding="UTF-8"?> mapper PUBLIC "-//mybatis.org//DTD com.example.demo.Mapper1 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.Mapper.BlogMapper"> <resultMap id="BaseMap" type="com.example.demo.Blog"> <id property="blogID" column="blogID">id> <result property="userID" column="userID">result> <result property="title" column="title">result> <result property="content" column="content">result> <association property="user" resultMap="com.example.demo.Mapper.UserMapper.BaseMap" columnPrefix="u_">association> resultMap> <select id="GetAll" resultMap="BaseMap"> select blog.*,user.userID as u_userID,user.classID as u_classID,user.password as u_password,user.username as u_username from blog left join user on user.userID=blog.userID; select> mapper>4)在们的blogMapper.xml中的代码如下:
"1.0" encoding="UTF-8"?> mapper PUBLIC "-//mybatis.org//DTD com.example.demo.Mapper1 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.Mapper.UserMapper"> <resultMap id="BaseMap" type="com.example.demo.User"> <id column="userID" property="userID">id> <result column="classID" property="classID">result> <result column="username" property="username">result> <result column="password" property="password">result> <collection property="list" resultMap="com.example.demo.Mapper.BlogMapper.BaseMap" columnPrefix="u_">collection> resultMap> <select id="GetAll" resultMap="BaseMap"> select user.*,blog.blogID as u_blogID,blog.userID as u_userID,blog.title as u_title,blog.content as u_content from user join blog on blog.userID=user.userID; select> mapper>结果:
logging.level.com.example.demo=debug