实验要求:
掌握MyBatis的关联映射使用方法。
实验内容:
实验1参考教材4.2、4.3和4.4小节的内容和案例的实现步骤,完成使用MyBatis 关联映射规则测试案例代码的编写。
实验2类图(说明:一个人具有多套房子的所有权)
类关联关系图
实现Person和House的一对多的单向关联关系。
1)查询出一个人的所有房屋的位置信息
2)根据房屋的位置信息查询该房屋所属主人的姓名。
实验3 完成权限管理功能的设计。要求:
1)1个用户拥有多个角色
2)1个角色拥有多个菜单功能
3)1个角色拥有多个用户
4)1个菜单功能可以分配给多个角色
根据以上关系要求,编写程序实现功能:
根据用户ID查找该用户能访问的所有菜单功能
实验分析:
- 实验1主要考查对MyBatis的关联映射的掌握。
- 实验2使用的注解方式实现。第一个要求为一对多,第二个为一对一。
- 实验3主要是两个多对多的关系,可以在数据库中建立5个表,可以清晰地找到各自的关系。使用配置文件完成嵌套结果查询。
根据实验在数据库中建立的5张表
实验操作所用工具(软件):
IntelliJ IDEA 2021.2.1
实验共用代码
Resource
db.properties(数据库连接配置文件)
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&\ characterEncoding=utf8&useUnicode=true&useSSL=false
username=root
password=1
log4j.properties(MyBatis和控制台日志配置文件)(非必要)
#全局日志配置
log4j.rootLogger=DEBUG,Console
#控制台输出配置
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
#日志输出级别
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
mybatis-config.xml(MyBatis的核心配置文件)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 外部属性文件读取 -->
<properties resource="db.properties"> </properties>
<settings>
<!-- 打开延迟加载的开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将积极加载改成消息加载,即按需加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- 别名 -->
<typeAliases>
<package name="com.cqust.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper class="com.cqust.dao.PersonMapper"/>
<mapper class="com.cqust.dao.HouseMapper"/>
<mapper resource="UsersMapper.xml"/>
</mappers>
</configuration>
utils层
MyBatisUtils类
package com.cqust.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.Reader;
/**
* 工具类
*/
public class MyBatisUtils {
private static SqlSessionFactory sqlSessionFactory = null;
//初始化SQLSessionFactory对象
static {
try{
//使用MyBatis提供的Resource类加载MyBatis的配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//构建SQLSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e){
e.printStackTrace();
}
}
//获取SqlSession对象的方法
public static SqlSession getSession(){
//若传入true表示关闭事务控制,自动提交;false表示开启事务控制
return sqlSessionFactory.openSession(true);
}
}
测试类
import com.cqust.dao.HouseMapper;
import com.cqust.dao.PersonMapper;
import com.cqust.dao.RolesMapper;
import com.cqust.dao.UsersMapper;
import com.cqust.pojo.House;
import com.cqust.pojo.Person;
import com.cqust.pojo.Roles;
import com.cqust.pojo.Users;
import com.cqust.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class Test1 {
/**
* 实验2_1
* @Select注解
* 一对多
* 查询出一个人的所有房屋的位置信息
*/
@Test
public void findPersonByIdTest() {
SqlSession session = MyBatisUtils.getSession();
PersonMapper mapper = session.getMapper(PersonMapper.class);
Person person = mapper.selectPersonById(1);
System.out.println(person);
session.close();
}
/**
* 实验2_2
* 一对一
* 根据房屋的位置信息查询该房屋所属主人的姓名
*/
@Test
public void findPersonByPositionTest() {
SqlSession session = MyBatisUtils.getSession();
HouseMapper mapper = session.getMapper(HouseMapper.class);
House house = mapper.selectHousesByPosition("深圳湾壹号");
System.out.println(house.toString());
session.close();
}
/**
* 实验3
* 多对多
* 根据房屋的位置信息查询该房屋所属主人的姓名
*/
@Test
public void findMenusByUserIdTest() {
SqlSession session = MyBatisUtils.getSession();
List<Users> users = session.selectList("selectUsersById",1);
for(Users u : users){
System.out.println(users.toString());
}
session.close();
}
}
实验1
实验2
dao层
PersonMapper接口
package com.cqust.dao;
import com.cqust.pojo.Person;
import org.apache.ibatis.annotations.*;
public interface PersonMapper {
// 根据个人id查询个人信息
@Select("select * from person where id=#{id}")
// @Results相当于ResultMap
@Results({@Result(id = true,column = "id",property = "id"),
@Result(column = "name",property = "name"),
// 关联映射house表中的id
@Result(column = "id",property = "houseList",
// @Many相当于collection
many = @Many(select = "com.cqust.dao.HouseMapper.selectHousesById"))})
Person selectPersonById(int id);
// 根据个人id查询个人信息
@Select("select * from person where id=#{id}")
Person selectPersonById1(int id);
}
HouseMapper接口
package com.cqust.dao;
import com.cqust.pojo.House;
import com.cqust.pojo.Person;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.type.JdbcType;
import java.util.List;
public interface HouseMapper {
// 根据个人id查询房屋信息
@Select("select * from house where person_id=#{person_id}")
@Results({@Result(id = true,column = "id",property = "id"),
@Result(column = "position",property = "position")})
List<House> selectHousesById(int person_id);
// 根据房屋位置查询房屋户主(person_id)
@Select("select * from house where position =#{position}")
@Results({@Result(id = true,column = "id",property = "id"),
@Result(column = "position",property = "position"),
@Result(column = "person_id",property = "person", javaType= Person.class,
one = @One(select = "com.cqust.dao.PersonMapper.selectPersonById1"))})
House selectHousesByPosition(String position);
}
pojo层
Person类
package com.cqust.pojo;
import java.util.List;
public class Person {
private int id;
private String name;
private List<House> houseList;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", houseList=" + houseList +
'}';
}
}
House类
package com.cqust.pojo;
public class House {
private int id;
private String position;
private Person person;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@Override
public String toString() {
return "House{" +
"id=" + id +
", 位置 = '" + position + '\'' +
// 根据房屋的位置信息查询该房屋所属主人的姓名
// ", 业主 = " + person.getName() +
'}';
}
}
实验3
配置层
UsersMapper.xml(映射文件)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cqust.pojo.Users">
<!-- 多对多嵌套结果查询 -->
<!-- 多表查询:通过用户ID查找该用户能访问的所有菜单功能 -->
<select id="selectUsersById" resultMap="selectUsersByIdResult">
select u.id,u.username,r.id as r_id,r.rolename,m.id as m_id,m.menuname,m.menupath
from menus m,roles r,users u,t_u_r t1,t_r_m t2
where m.id=t2.mid
and t2.rid=r.id
and r.id=t1.roleid
and t1.uid=u.id
and u.id=#{id}
</select>
<resultMap id="selectUsersByIdResult" type="users">
<id property="id" column="id"/>
<result property="username" column="username"/>
<!-- collection中嵌套一个collection -->
<collection property="rolesList" ofType="roles">
<id property="id" column="r_id"/>
<result property="rolename" column="rolename"/>
<collection property="menus" ofType="menus">
<id property="id" column="m_id"/>
<result property="menuname" column="menuname"/>
<result property="menupath" column="menupath"/>
</collection>
</collection>
</resultMap>
</mapper>
pojo层
Users类
package com.cqust.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/*@Data
@AllArgsConstructor
@NoArgsConstructor*/
public class Users {
private int id;
private String username;
private String password;
private List<Roles> rolesList;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<Roles> getRolesList() {
return rolesList;
}
public void setRolesList(List<Roles> rolesList) {
this.rolesList = rolesList;
}
@Override
public String toString() {
return "Users{" +
"id=" + id +
", username='" + username + '\'' +
", rolesList=" + rolesList +
'}';
}
}
Roles类
package com.cqust.pojo;
import java.util.List;
public class Roles {
private int id;
private String rolename;
private List<Menus> menus;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRolename() {
return rolename;
}
public void setRolename(String rolename) {
this.rolename = rolename;
}
public List<Menus> getMenus() {
return menus;
}
public void setMenus(List<Menus> menus) {
this.menus = menus;
}
@Override
public String toString() {
return "Roles{" +
"id=" + id +
", rolename='" + rolename + '\'' +
", menus=" + menus +
'}';
}
}
Menus类
package com.cqust.pojo;
public class Menus {
private int id;
private String menuname;
private String menupath;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMenuname() {
return menuname;
}
public void setMenuname(String menuname) {
this.menuname = menuname;
}
public String getMenupath() {
return menupath;
}
public void setMenupath(String menupath) {
this.menupath = menupath;
}
@Override
public String toString() {
return "Menus{" +
", menuname='" + menuname + '\'' +
", menupath='" + menupath + '\'' +
'}';
}
}
程序运行结果:
实验2:
实验3:
实验总结:
本次实验主要是对实验2、3的书写,实验2主要运用了注解方式编写,起初打算实验3也使用注解方式编写,但是在@Many嵌套过程中遇到了麻烦,用了很多办法也没有解决,最终决定还是采用配置文件的方式编写,使用嵌套结果查询,最终也顺利实现了实验要求。这个版本的代码写的非常的粗糙鄙陋,希望后期学到新知识后能进行改进(本人真的很懒哈哈哈!)。
写在最后:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!
谢谢浏览!