mybatis(上)

news2024/11/26 10:48:40

mybatis:原来是apache的一个开源项目,叫ibatis。2010年转移谷歌,从3.0开始改名为mybatis
mybatis是一款优秀的持久层框架,是对jdbc功能进行轻量级的封装,提供了统一的数据库信息配置统一放在一个xml文件中,读取就行。将sql提取到一个xml文件中,提供了动态sql功能,提供了结果自动映射封装。
是一个orm(ORM Object Relational Mapping 对象关系映射)实现,orm指的是,将数据中的记录与java中的对象进行关系映射
对jdbc原生接口进行封装,提供了一些mybatis自己的接口和类来实现

MyBatis 环境搭建

1.创建一个maven项目, 把项目添加到git仓库
2.创建数据库表,创建对应的类

create database ssmdb charset utf8
create table admin(
	id int primary key auto_increment,
	account varchar(30),
	password varchar(50)
)
package com.ffyc.mybatisPro.model;
public class Admin {
    private int id;
    private String account;
    private String password;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "Admin{" +
                "id=" + id +
                ", account='" + account + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

3.添加mybatis相关的依赖 mybatis、mysql

<dependencies>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.16</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.2</version>
    </dependency>
</dependencies>

4.创建一个mybatis的核心配置文件

  • 数据库连接部分信息
  • sql映射文件
<!--自己用的配置文件在resources,New/File下创建一个文件mybatis_config.xml-->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="config.properties"></properties>  <!--导入配置属性文件-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/> <!--数据事务管理配置-->
            <dataSource type="POOLED"> <!--数据源配置,type="POOLED"使用数据库连接池-->
                <property name="driver" value="${classDriverName}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${uname}"/>
                <property name="password" value="${pwd}"/>
            </dataSource>
        </environment>
     <!--   <environment id="work">
        </environment>-->
    </environments>
    <mappers> <!--配置SQL映射文件-->
        <mapper resource="mappers/AdminMapper.xml"/>
    </mappers>
</configuration>
//在resources/config.properties中
classDriverName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/ssmdb?serverTimezone=Asia/Shanghai
uname=root
pwd=123456

5.开发了接口

package com.ffyc.mybatisPro.dao;

import com.ffyc.mybatisPro.model.Admin;
//通过id,查询之后返回Admin对象
public interface AdminDao {
    Admin findAdminById(int id);
}

6.创建了sql映射文件

/*在resources/mappers/adminMapper.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.ffyc.mybatisPro.dao.AdminDao"> <!--和接口名字一致-->
    <select id="findAdminById" parameterType="int" resultType="Admin">  /*可以直接写Admin*/
        select id,account,password from admin where id=#{id}
    </select>
</mapper>

MybatisX插件,可以切换接口SQL映射
在这里插入图片描述在这里插入图片描述
7.测试
SqLSessionFactory用来封装配置信息,主要用来创建SqLSession对象。由于SqLSessionFactory对象创建开销较大,所以一个项目中只创建一个,不用关闭
SqLSession用来每次与数据库会话使用的,每次与数据库交互一次都需要创建一个独立的sqlSession

package com.ffyc.mybatisPro.test;
public class Test {
    public static void main(String[] args) throws IOException {
        Reader reader = Resources.getResourceAsReader("mybatis_config.xml");//读取配置文件
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);//创建SqlSessionFactory
        SqlSession sqlSession = sessionFactory.openSession();//创建SqlSession
        //AdminDao.class(拿到类被加载到内存中的CLass对象),getMapper创建了接口的代理对象
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
        Admin admin = adminDao.findAdminById(1);//调用接口中方法 对应的sql
        System.out.println(admin);
        sqlSession.close();//关闭了sqlSession,不用关闭sessionFactory
    }
}

xml配置

配置类型简称

<typeAliases> <!--配置类型简称-->
    <!--<typeAlias type="com.ffyc.mybatisPro.model" alias="Admin"></typeAlias>-->
    <package name="com.ffyc.mybatisPro.model"/>
</typeAliases>
<?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.ffyc.mybatisPro.dao.AdminDao">
    <select id="findAdminById" parameterType="int" resultType="Admin">  /*可以直接写Admin*/
        select id,account,password from admin where id=#{id}
    </select>
</mapper>

常用设置

<settings> <!--常用设置-->
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

junit单元测试

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>provided</scope> 
</dependency>
package com.ffyc.mybatisPro.test;

public class Test1 {
    @Test
    public void find(){
        System.out.println("aaa");
    }
    @Test
    public void save(){
        System.out.println("bbb");
    }
}

对Test代码进行封装

package com.ffyc.mybatisPro.util;

public class MybatisUtil {
    static SqlSessionFactory sessionFactory;
    //静态代码块,在类加载时执行一次
    static {
        Reader reader = null;
        try {
            reader = Resources.getResourceAsReader("mybatis_config.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        sessionFactory = new SqlSessionFactoryBuilder().build(reader);
    }
    //创建并返回SqlSession
    public static SqlSession getSqlSession(){
        return sessionFactory.openSession();
    }
}
public class Test1 {
    @Test
    public void find(){
        SqlSession sqlSession= MybatisUtil.getSqlSession();
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
        Admin admin = adminDao.findAdminById(1);//调用接口中方法 对应的sql
        System.out.println(admin);
        sqlSession.close();
    }
}

参数传递

1.基本类型的单个参数,直接传递

public interface AdminDao {
    Admin findAdminById(int id);
}
<mapper namespace="com.ffyc.mybatisPro.dao.AdminDao"> <!--和接口名字一致-->
   <select id="findAdminById" parameterType="int" resultType="com.ffyc.mybatisPro.model.Admin">  /*可以直接写Admin*/
        select id,account,password from admin where id=#{id}
    </select>
</mapper>
public class Test1 {
    @Test
    public void find(){
        SqlSession sqlSession= MybatisUtil.getSqlSession();
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
        Admin admin = adminDao.findAdminById(1);//调用接口中方法 对应的sql
        System.out.println(admin);
        sqlSession.close();
    }
}

2.多个参数传递
方法一:多个参数、或引用类型使用注解标签@Param绑定

public interface AdminDao {
    Admin login(@Param("acc")String account, @Param("pwd") String password);
}
<mapper namespace="com.ffyc.mybatisPro.dao.AdminDao"> <!--和接口名字一致-->
    <select id="login" resultType="com.ffyc.mybatisPro.model.Admin">
        select * from admin where account=#{acc} and password=#{pwd}
    </select>
</mapper>
public class Test1 {
    @Test
    public void login(){
        SqlSession sqlSession= MybatisUtil.getSqlSession();
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
        Admin admin = adminDao.login("admin","admin");//调用接口中方法 对应的sql
        System.out.println(admin);
        sqlSession.close();
    }
}

方法二:多个参数封装到一个对象中(推荐)

public interface AdminDao {
    Admin login2(Admin admin);
}
<mapper namespace="com.ffyc.mybatisPro.dao.AdminDao"> <!--和接口名字一致-->
    <select id="login2" parameterType="com.ffyc.mybatisPro.model.Admin" resultType="com.ffyc.mybatisPro.model.Admin">
        select * from admin where account=#{account} and password=#{password} /*model里面的属性*/
    </select>
</mapper>
public class Test1 {
    @Test
    public void login2(){
        SqlSession sqlSession= MybatisUtil.getSqlSession();
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
        Admin admin=new Admin();
        admin.setAccount("admin");
        admin.setPassword("admin");
        Admin a= adminDao.login2(admin);//调用接口中方法 对应的sql
        System.out.println(a);
        sqlSession.close();
    }
}

3.字符串类型单独传递时,需要进行绑定处理
SQL中接收参数:#{} 和${}区别(面试必问)

  • #{参数名} 占位符,预编译方式传值,编译好 SQL 语句再取值,#方式能够防止 sql 注入,更安全
    select * from admin where account=#{account} and password=#{password}
    在这里插入图片描述
  • 参数名拼接符,主要用来动态的向 s q l 中 ∗ ∗ 传列名 ∗ ∗ ;传值时是直接将参数拼接到 s q l 中 ( 不建议 ) ,需要加单引号,会传入参数字符串,取值以后再去编译 S Q L 语句,无法防止 S q l 注入 s e l e c t ∗ f r o m a d m i n w h e r e a c c o u n t = ′ {参数名} 拼接符,主要用来动态的向sql中**传列名**;传值时是直接将参数拼接到sql中(不建议),需要加单引号,会传入参数字符串,取值以后再去编译 SQL 语句,无法防止 Sql 注入 select * from admin where account=' 参数名拼接符,主要用来动态的向sql传列名;传值时是直接将参数拼接到sql(不建议),需要加单引号,会传入参数字符串,取值以后再去编译SQL语句,无法防止Sql注入selectfromadminwhereaccount={account}’ and password=‘${password}’
    在这里插入图片描述
    select * from admin where ${column}=‘admin’
  • 注意:MyBatis 排序时使用 order by 动态参数时需要注意,用$而不是#
    select * from admin order by ${column} 动态传列名
public interface AdminDao {
    Admin find2(@Param("column")String column);
}
<select id="find2" parameterType="String" resultType="com.ffyc.mybatisPro.model.Admin">
    select * from admin where ${column}='admin'
</select>
@Test
public void find2(){
    SqlSession sqlSession= MybatisUtil.getSqlSession();
    AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
    Admin admin = adminDao.find2("account");//调用接口中方法 对应的sql
    System.out.println(admin);
    sqlSession.close();
}

新增

public interface AdminDao {
    void saveAdmin(Admin admin);
}
<insert id="saveAdmin" parameterType="com.ffyc.mybatisPro.model.Admin">
    insert into admin(account,password) values (#{account},#{password})
</insert>

事务: 我们每次对数据库连接上,发送sql到执行完,数据库有一个机制进行控制开启事务
做一个转账操作

sql1 -100
java… 异常
sql2 +100
java…
提交事务:当我们做完所有的事情之后,提交事务,数据库真正的执行

jdbc默认是自动提交事务;mybatis把自动事务提交关闭了:Setting autocommit to false,需要在所有的业务代码执行成功后,手动提交事务

@Test
public void save(){
    SqlSession sqlSession= MybatisUtil.getSqlSession();
    AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
    Admin admin=new Admin();
    admin.setAccount("zhangsan");
    admin.setPassword("zhangsan");
    adminDao.saveAdmin(admin);//调用接口中方法 对应的sql
    sqlSession.commit();//提交事务;新增,修改,删除操作尽量都在事务控制中进行
    sqlSession.close();
}

保存管理员后,立即拿到id
开启将生成的主键列,自动封装到对象中

<!--keyProperty="id"是类中的属性名,keyColumn="id"是数据库中的列名;把数据库生成的主键拿到赋给Admin对象中的id属性-->
<insert id="saveAdmin" parameterType="com.ffyc.mybatisPro.model.Admin" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
    insert into admin(account,password) values (#{account},#{password})
</insert>
@Test
    public void save(){
        SqlSession sqlSession= MybatisUtil.getSqlSession();
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
        Admin admin=new Admin();
        admin.setAccount("zhangsan");
        admin.setPassword("zhangsan");
        adminDao.saveAdmin(admin);//调用接口中方法 对应的sql
        System.out.println(admin.getId());
        sqlSession.commit();//提交事务;新增,修改,删除操作尽量都在事务控制中进行
        sqlSession.close();
    }

修改

public interface AdminDao {
    void updateAdmin(Admin admin);
}
<update id="updateAdmin" parameterType="com.ffyc.mybatisPro.model.Admin">
    update admin set account=#{account},password=#{password} where id=#{id}
</update>
@Test
public void update(){
    SqlSession sqlSession= MybatisUtil.getSqlSession();
    AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
    Admin admin=new Admin();
    admin.setId(4);
    admin.setAccount("lisi");
    admin.setPassword("lisi");
    adminDao.updateAdmin(admin);//调用接口中方法 对应的sql
    sqlSession.commit();//提交事务;新增,修改,删除操作尽量都在事务控制中进行
    sqlSession.close();
}

删除,通过id删除管理员

public interface AdminDao {
    void deleteAdminById(int id);
}
<delete id="deleteAdminById" parameterType="int">
    delete from admin where id=#{id}
</delete>
@Test
public void delete(){
    SqlSession sqlSession= MybatisUtil.getSqlSession();
    AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
    adminDao.deleteAdminById(4);//调用接口中方法 对应的sql
    sqlSession.commit();//提交事务;新增,修改,删除操作尽量都在事务控制中进行
    sqlSession.close();
}

查询

1、单张表查询

1.查询管理员的总数

public interface AdminDao {
    //查询管理员的总数
    int adminCount();
}
<select id="adminCount" resultType="int">
    select count(*) from admin
</select>
@Test
    public void find(){
        SqlSession sqlSession= MybatisUtil.getSqlSession();
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
        int count=adminDao.adminCount();//调用接口中方法 对应的sql
        System.out.println(count);
        sqlSession.close();
    }
设置名描述有效值默认值
autoMappingBehavior指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。NONE, PARTIAL, FULLPARTIAL
mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN映射到经典 Java 属性名 aColumn。true | falseFalse
2.通过id查询
public interface AdminDao {
    Admin findAdminById(int id);
}

mybatis会将查询到的结果自动封装到一个对象中,会自己创建给定类型的类的对象
自动封装结果的条件:

  1. 开启了全局的自动结果映射,PARTIAL默认是单张表开启的
  2. 数据库列名与属性名名字相同;如果名字不一致,不能映射,可以定义别名使其一致
  3. mapUnderscoreToCamelCase = true;数据库中admin_gender可以映射到类中的adminGender
<!--mybatis会将查询到的结果自动封装到一个对象中,会自己创建给定类型的类的对象-->
<select id="findAdminById" parameterType="int" resultType="com.ffyc.mybatisPro.model.Admin">
    select id,account,password,admin_gender from admin where id=#{id}
</select>
@Test
public void find2(){
    SqlSession sqlSession= MybatisUtil.getSqlSession();
    AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
    Admin admin=adminDao.findAdminById(1);//调用接口中方法 对应的sql
    System.out.println(admin);
    sqlSession.close();
}
<settings> <!--常用设置-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

3.查询多个管理员,先创建对象然后自动装入集合中

public interface AdminDao {
    List<Admin>  findAdmins();
}
<select id="findAdmins" resultType="com.ffyc.mybatisPro.model.Admin">
    select id,account,password,admin_gender from admin
</select>
@Test
public void find3(){
    SqlSession sqlSession= MybatisUtil.getSqlSession();
    AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
    List<Admin> list=adminDao.findAdmins();//调用接口中方法 对应的sql
    System.out.println(list);
    sqlSession.close();
}
<settings> <!--常用设置-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

在resultMap标签中,可以进行自定义的结果映射
column="admin_gender"是数据库中的, property="gender"是类中的

<!--在resultMap标签中,可以进行自定义的结果映射-->
<resultMap id="adminMap" type="com.ffyc.mybatisPro.model.Admin">
    <id column="id" property="id"></id>
    <result column="account" property="account"></result>
    <result column="password" property="password"></result>
    <result column="admin_gender" property="gender"></result>
</resultMap>
<select id="findAdmins" resultType="com.ffyc.mybatisPro.model.Admin" resultMap="adminMap">
    select id,account,password,admin_gender from admin
</select>

2、多张表查询

2.1关联查询

1.通过id查询学生
数据库

create table student(
	id int primary key auto_increment,
	num int,
	name varchar(10),
	gender char(1),
	birthday date,
	dormid int,
	adminid int,
	oper_time datetime
)

create table dorm(
	id int primary key auto_increment,
	num int
)

注意:
建议模型类中的属性基本类型都使用包装类型,因为引用类型默认值为null
一旦类中定义了有参构造方法,一定要把无参构造方法显示的定义出来,因为框架需要使用它
java中可以进行方法重载,mybatis中不行,因为.xml是通过id(接口的方法名)区分的
在这里插入图片描述

package com.ffyc.mybatisPro.model;
public class Student {
    private Integer id;//建议使用引用类型,默认值为null
    private Integer num;
    private String name;
    private String gender;
    private Date birthday;
    private Dorm dorm;//关联关系,一个类关联另一个类
    private Admin admin;
    private Date operTime;
    //get和set方法
}
package com.ffyc.mybatisPro.model;
public class Dorm {
    private int id;
    private int num;//宿舍号
    private  Admin admin;
    private List<Student> students;//一个宿舍对应多个学生

    public Admin getAdmin() {
        return admin;
    }

    public void setAdmin(Admin admin) {
        this.admin = admin;
    }

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    @Override
    public String toString() {
        return "Dorm{" +
                "id=" + id +
                ", num=" + num +
                '}';
    }
}
public interface StudentDao {
    Student findStudentById(int id);
}
<?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.ffyc.mybatisPro.dao.StudentDao">
    <resultMap id="studentMap" type="com.ffyc.mybatisPro.model.Student">
        <id column="id" property="id"></id>
        <result column="num" property="num"></result>
        <result column="name" property="name"></result>
        <result column="gender" property="gender"></result>
        <result column="birthday" property="birthday"></result>
        <result column="oper_time" property="operTime"></result>
       <!-- 用来封装关联的对象信息,property="dorm",就会创建一个关联的对象-->
        <!--column="dormNum"是学生中的, property="num"是dorm中的-->
        <association property="dorm" javaType="com.ffyc.mybatisPro.model.Dorm">
            <result column="dormNum" property="num"></result>
        </association>
        <association property="admin" javaType="com.ffyc.mybatisPro.model.Admin">
            <result column="account" property="account"></result>
        </association>
    </resultMap>
    <select id="findStudentById" parameterType="int" resultMap="studentMap">
        select
        s.id,
        s.num,
        s.name,
        s.gender,
        s.birthday,
        d.num dormNum,
        a.account,
        s.oper_time
    from student s left join dorm d on s.dormid=d.id
                left join admin a on s.adminid=a.id
                where s.id=#{id}
    </select>
</mapper>
public class TestStudent {
    @Test
    public void find(){
        SqlSession sqlSession= MybatisUtil.getSqlSession();
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        Student student =studentDao.findStudentById(1);//调用接口中方法 对应的sql
        System.out.println(student.getNum());//拿到学号
        System.out.println(student.getDorm().getNum());//拿到宿舍号
        sqlSession.close();
    }
}

mybatis默认配置是:一旦出现了套关联查询,就不自动映射,可以开启(可以映射的都赋值);如果在resultMap标签中进行自定义的结果映射就不需要这个(把指定的赋值)

<settings> <!--常用设置-->
    <setting name="autoMappingBehavior" value="FULL"/>
</settings>

2.查询多个学生

public interface StudentDao {
    List<Student> findStudents();
}
<resultMap id="studentMap" type="com.ffyc.mybatisPro.model.Student">
    <id column="id" property="id"></id>
    <result column="num" property="num"></result>
    <result column="name" property="name"></result>
    <result column="gender" property="gender"></result>
    <result column="birthday" property="birthday"></result>
    <result column="oper_time" property="operTime"></result>
   <!-- 用来封装关联的对象信息,property="dorm",就会创建一个关联的对象-->
    <!--column="dormNum"是学生中的, property="num"是dorm中的-->
    <association property="dorm" javaType="com.ffyc.mybatisPro.model.Dorm">
        <result column="dormNum" property="num"></result>
    </association>
    <association property="admin" javaType="com.ffyc.mybatisPro.model.Admin">
        <result column="account" property="account"></result>
    </association>
</resultMap> 
<select id="findStudents" resultMap="studentMap">
    select
    s.id,
    s.num,
    s.name,
    s.gender,
    s.birthday,
    d.num dormNum,
    a.account,
    s.oper_time
    from student s left join dorm d on s.dormid=d.id
            left join admin a on s.adminid=a.id
</select>
@Test
public void find2(){
    SqlSession sqlSession= MybatisUtil.getSqlSession();
    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    List<Student> list=studentDao.findStudents();//调用接口中方法 对应的sql
    System.out.println(list);
    sqlSession.close();
}
2.2嵌套查询

使用嵌套查询,把sql分成多次查询,先查询学生信息,然后再查询宿舍、管理员

public interface StudentDao {
    Student findStudentById1(int id);
}
<resultMap id="studentMap1" type="com.ffyc.mybatisPro.model.Student">
    <id column="id" property="id"></id>
    <result column="num" property="num"></result>
    <result column="name" property="name"></result>
    <result column="gender" property="gender"></result>
    <result column="birthday" property="birthday"></result>
    <result column="oper_time" property="operTime"></result>
    <association property="dorm" javaType="com.ffyc.mybatisPro.model.Dorm" column="dormid" select="findDormById"></association>
    <association property="admin" javaType="com.ffyc.mybatisPro.model.Admin" column="adminid" select="findAdminById"></association>
</resultMap>
<select id="findStudentById1" parameterType="int" resultMap="studentMap1">
    select id,num,name,gender,birthday,dormid,adminid from student where id=#{id}
</select>
<select id="findDormById" resultType="com.ffyc.mybatisPro.model.Dorm">
    select num from dorm where id=#{dormid}   /*dormid是column="dormid"传过来的*/
</select>
<select id="findAdminById" resultType="com.ffyc.mybatisPro.model.Admin">
    select account from admin where id=#{adminid}
</select>
@Test
public void find3(){
    SqlSession sqlSession= MybatisUtil.getSqlSession();
    StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    studentDao.findStudentById1(1);//调用接口中方法 对应的sql
    sqlSession.close();
}

2.3 查询宿舍下所有的学生
宿舍和学生关联的话,会有多条记录,但是对于宿舍只有一个记录;将关联多个学生封装到一个集合对象中,在宿舍里面放一个学生的集合

public interface DormDao {
    Dorm findDormById(int id);
}
<mapper namespace="com.ffyc.mybatisPro.dao.DormDao">
    <resultMap id="dormMap" type="com.ffyc.mybatisPro.model.Dorm">
        <id column="id" property="id"></id>
        <result column="num" property="num"></result>
        <association property="admin" javaType="com.ffyc.mybatisPro.model.Admin">
            <result column="account" property="account"></result>
        </association>
        <!--用collection最终返回一个对象;ofType是:list类型中装的Student类型-->
        <collection property="students" javaType="list" ofType="com.ffyc.mybatisPro.model.Student">
            <!--result column="name"是Dorm中, property="name"是Student类中-->
            <result column="snum" property="num"></result>
            <result column="name" property="name"></result>
        </collection>
    </resultMap>
    <select id="findDormById" parameterType="int" resultMap="dormMap">
        select
            d.id,
            d.num,
            s.num snum,
            s.name,
            a.account
        from dorm d left join admin a on d.adminid=a.id
                     left join student s on d.id=s.dormid
                     where d.id=#{id}
    </select>
</mapper>
@Test
public void find(){
    SqlSession sqlSession= MybatisUtil.getSqlSession();
    DormDao dormDao = sqlSession.getMapper(DormDao.class);
    Dorm dorm =dormDao.findDormById(1);//调用接口中方法 对应的sql
    sqlSession.close();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/867680.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安卓改透明屏有哪些方法和步骤?壁纸、主题、软件

安卓改透明屏是指将安卓手机的屏幕背景变为透明&#xff0c;使得手机的背景图像或者壁纸能够透过屏幕显示出来。 这样的改变可以让手机的界面更加个性化&#xff0c;也能够增加手机的美观度。 要实现安卓手机的透明屏&#xff0c;可以通过以下几种方法&#xff1a; 1. 使用透…

Windows端口占用问题

Windows端口占用问题 1、检查端口是否已被占用&#xff08;端口举例&#xff1a;10000&#xff09; 【WindowsR】打开【运行】窗口 点击【确定】打开【cmd】窗口 输入【下方命令】&#xff0c;然后【回车】 netstat -aon | find "10000"可以看到端口【10000】已…

Android系统-进程-Binder

目录 引言&#xff1a; 一次拷贝 Binder一次通信过程 应用启动中的binder交互 C/S模式&#xff1a; Binder COMMAND BWR数据结构&#xff1a; 引言&#xff1a; Android的binder是从openbinder发展过来的。包括了binder驱动&#xff0c;Native层&#xff0c;Java层。用…

Linux黑客渗透测试揭秘:探索安全边界的挑战与应对

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 前言 随着信息技术的迅…

uniapp 获取 view 的宽度、高度以及上下左右左边界位置

<view class"cont-box"></view> /* 获取节点信息的对象 */ getElementRect() {const query uni.createSelectorQuery().in(this);query.select(".cont-box").boundingClientRect(res > {console.log(res);console.log(res.height); // 10…

高级进阶多线程——多任务处理、线程状态(生命周期)、三种创建多线程的方式

Java多线程 Java中的多线程是一个同时执行多个线程的进程。线程是一个轻量级的子进程&#xff0c;是最小的处理单元。多进程和多线程都用于实现多任务处理。 但是&#xff0c;一般使用多线程而不是多进程&#xff0c;这是因为线程使用共享内存区域。它们不分配单独的内存区域…

勘探开发人工智能技术:机器学习(6)

0 提纲 7.1 循环神经网络RNN 7.2 LSTM 7.3 Transformer 7.4 U-Net 1 循环神经网络RNN 把上一时刻的输出作为下一时刻的输入之一. 1.1 全连接神经网络的缺点 现在的任务是要利用如下语料来给apple打标签&#xff1a; 第一句话&#xff1a;I like eating apple!(我喜欢吃苹…

优秀的 Modbus 从站(从机、服务端)仿真器、串口调试工具

文章目录 优秀的 Modbus 从站&#xff08;从机、服务端&#xff09;仿真器、串口调试工具主要功能软件截图 优秀的 Modbus 从站&#xff08;从机、服务端&#xff09;仿真器、串口调试工具 官网下载地址&#xff1a;http://www.redisant.cn/mse 主要功能 支持多种Modbus协议…

NVIDIA TX2 NX编译及更新设备树

在NVIDIA官网下载相关文件 官网网址:https://developer.nvidia.com/embedded/jetson-linux-archive 我选择的版本为R32.7.4 需要下载3个文件,BSP、根文件系统、BSP源码: 解压 将Tegra_Linux_Sample-Root-Filesystem_R32.7.4_aarch64文件夹下的内容提取到Jetson_Linux_R32.…

【C++入门到精通】C++入门 —— vector (STL)

阅读导航 前言一、vector简介1. 概念2. 特点 二、vector的使用1.vector 构造函数2. vector 空间增长问题⭕resize 和 reserve 函数 3. vector 增删查改⭕operator[] 函数 三、迭代器失效温馨提示 前言 前面我们讲了C语言的基础知识&#xff0c;也了解了一些数据结构&#xff0…

2023年七夕情人节是什么时候? 淘宝天猫七夕节礼物优惠券怎么领取?

2023年七夕情人节是什么时候&#xff1f; 2023年七夕节时间是2023年8月22日&#xff08;农历七月初七&#xff0c;星期二&#xff09;&#xff1b; 七夕情人节&#xff0c;又称中国情人节&#xff0c;是浪漫的代名词。源自古人对牛郎织女一年一度相会的仰望&#xff0c;这一天…

Simulink仿真模块 -Scope

Scope模块的作用是显示仿真过程中生成的信号。它包含在以下库中: 库: Simulink / Commonly Used BlocksSimulink / SinksHDL Coder / Commonly Used BlocksHDL Coder / Sinks 如图所示: Simulink Scope 模块和 DSP System Toolbox™ Time Scope 模块显示时域信号。…

PAT(Advanced Level) Practice(with python)——1058 A+B in Hogwarts

Code A,B map(str,input().split()) g1,s1,k1 A.split(.) g2,s2,k2 B.split(.) g int(g1)int(g2) s int(s1)int(s2) k int(k1)int(k2) if k>29:s1k%29 if s>17:g1s%17 print(str(g).str(s).str(k))

HCIP BGP实验

题目 拓扑图 配置IP地址及环回 R1 <Huawei>sy Enter system view, return user view with CtrlZ. [Huawei]sysname r1 [r1]int l0 [r1-LoopBack0]ip add 1.1.1.1 24 [r1-LoopBack0]int g0/0/0 [r1-GigabitEthernet0/0/0]ip add 12.1.1.1 24R2 <Huawei>sy Enter …

“继承”与“组合”的区分以及应用场景

0、引言 平常一般继承与接口听得多一些&#xff0c;组合个人感觉很少听说&#xff0c;实际上平时也有接触过&#xff0c;需要对该概念加深理解。 1、继承与组合 继承不必多言&#xff0c;子类继承父类&#xff0c;可以使用父类的非private&#xff08;或者default&#xff09;…

服务器遭受攻击之后的常见思路

哈喽大家好&#xff0c;我是咸鱼 不知道大家有没有看过这么一部电影&#xff1a; 这部电影讲述了男主是一个电脑极客&#xff0c;在计算机方面有着不可思议的天赋&#xff0c;男主所在的黑客组织凭借着超高的黑客技术去入侵各种国家机构的系统&#xff0c;并引起了德国秘密警察…

【变形金刚01】attention和transformer所有信息

图1.来源&#xff1a;Arseny Togulev在Unsplash上的照片 一、说明 这是一篇 长文 &#xff0c;几乎讨论了人们需要了解的有关注意力机制的所有信息&#xff0c;包括自我注意、查询、键、值、多头注意力、屏蔽多头注意力和转换器&#xff0c;包括有关 BERT 和 GPT 的一些细节。因…

VS2015+cublas实操记录(cuda加速GEMM矩阵乘加算子)

1. 环境配置&#xff1a; cuda安装后一般的安装位置在&#xff1a;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8 把这个目录下的include和lib分别配置在vs中&#xff0c;安装cuda教程可参考&#xff1a;https://zhuanlan.zhihu.com/p/520995962&#xff08;笔者…

干货满满的Python知识,学会这些你也能成为大牛

目录 1. 爬取网站数据 2. 数据清洗与处理 3. 数据可视化 4. 机器学习模型训练 5. 深度学习模型训练 6. 总结 1. 爬取网站数据 在我们的Python中呢&#xff0c;使用爬虫可以轻松地获取网站的数据。可以使用urllib、requests、BeautifulSoup等库进行数据爬取和处理。以下是…

【MySQL--->数据库操作】

文章目录 [TOC](文章目录) 一、操作语句1.增2.删3.改4.查5.备份 二、字符集与校验规则 一、操作语句 1.增 语句格式:create database [if no exists]数据库名[create_specification [,create_specification] …]; 中括号内是可选项,if no exists是指如果数据库不存在就创建,存…