【Mybatis 】什么是mybatis?如何在普通项目中使用?(超详细建议收藏)

在这里插入图片描述

文章目录

  • mybatis
    • 第一章
      • 1、什么是mybatis
      • 2、idea中配置环境
      • 3、创建一个普通工程
    • 第二章
      • 1、mybatis基本步骤
      • 2、导入log4j日志
      • 3、使用lombok注解
      • 4、mapper.xml文件详情
        • 1、parameterType属性
        • 2、resultType属性
      • 5、对实体包进行扫描
      • 6、SQL语句中的占位符及转义符
      • 7、接口方法包含多个参数
      • 8、resultMap手动封装
        • 1、手动封装解决
        • 2、起别名解决
        • 3、resultMap与resultType的区别
      • 9、查询
        • 1、按成绩范围查询
        • 2、区间查询
        • 3、模糊查询
        • 4、多条件查询(不确定有几个查询条件)
        • 5、条件查询的参数接受方式
          • **散装参数的接收**
          • **对象参数的接收**
          • **集合参数的接收**
        • 6、分页查询
      • 10、动态sql查询
      • 11、添加
      • 12、修改
        • 1、修改全部字段
        • 2、动态修改字段
      • 13、删除
        • 1、删除一个
        • 2、批量删除
    • 第三章
      • 1、基本语法
        • 1、代码片段
      • 2、返回类型
      • 3、插件
        • 1、使用步骤
      • 4、mybatis的关联查询
        • 1、一对多以及多对一
          • 实体类
          • **注意**
          • 1、多对一的关联查询
          • 2、一对多的关联查询
          • 3、延迟加载

mybatis

第一章

1、什么是mybatis

mybatis是一个持久层框架。它主要是用于简化数据库的操作

持久层:与数据库交互的层次就叫持久层

前身:在ibatis框架上产生的新框架

开发时比较流行的一种框架组合方式:

ssm:(spring+springmvc+mybatis)

mybatis必须要与spring配合使用才能变的更简单
//单独使用会很麻烦:

2、idea中配置环境

1、在idea中配置mybatis的mapper.xml文件与mybatis-config.xml文件

mapper.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="">
  
</mapper>

mybatis-config.xml

<?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=""/>
	
	<!-- 配置别名  -->
	<typeAliases>
	</typeAliases>
	
	<!-- 配置mybatis的运行环境 -->
	<environments default="development">
		<environment id="development">
			<!-- 采用的事务方式 -->
			<transactionManager type="jdbc" />
			<!-- 配置数据源信息 -->
			<dataSource type="pooled">
				<property name="url" value="${url}" />
				<property name="driver" value="${driver}" />
				<property name="username" value="${user}" />
				<property name="password" value="${pwd}" />
		</dataSource>
		</environment>
	</environments>
	
	<!-- 注册映射文件 -->
	<mappers>
		<mapper resource=""/>
	</mappers>

</configuration>

3、创建一个普通工程

1、创建普通工程

2、在main目录下,新增resources目录,用于存放配置文件(*.xml,*.properties)

3、导入依赖
	1、mybatis---->3.3.1
	2、mysql-connector-java----->5.1.47--->scope:runtime
	
4、在resources导入一个jdbc.properties,用于指定连接的数据库
            driver=com.mysql.jdbc.Driver
            url=jdbc:mysql://localhost:3306/ajaxinfo?      			useUnicode=true&characterEncoding=UTF-8
            user=root
            pwd=123456
            
5、创建resources目录下创建mybatis的主配置文件:mybatis-config.xml
			添数据时用el表达式
			${url}
			${driver}
			...
			
6、修改mybatis-config.xml文件
		<!-- 引用属性文件 -->
		<properties resource="jdbc.properties"/>
		
		
7、编写实体类与数据库结构对应
		stuInfo.java

8、编写数据访问层dao接口
		命名规范:xxxmapper(以前以dao结尾,现在以mapper结尾)
				userMapper
		//数据访问层接口
            public interface userMapper {
                public  void add(userInfo user);
                
			}

9、创建resources目录下创建mapper.xml文件,用于封装对stu表操作的所有sql语句
		//此处有坑
		要求:1、mapper.xml文件必须放在resources目录下
			2、mapper.xml的目录结构必须要与stuMapper接口的目录名一致
				//坑(不能一步创建,必须分开创建包org->java->dao)
			3、接口名必须与xml名保持一致,只是后缀名不同而已
				接口:stuMapper.java
				配置文件名:stuMapper.xml
			4、mapper.xml文件中的namespace(命名空间)必须是mapper接口的全路径
				全路径:包名加接口名
			5、采用对应的标签封装对应的sql语句
				insert,update,delete,select
			6、语句的id名称必须与mapper接口中的方法名同名,并且参数名称也要同名
			<mapper namespace="org.java.dao.userMapper">
                <!--添加-->
                <insert id="add" parameterType="org.java.enty.userInfo">
                    insert  into  user values(null,#{name},#{pwd},null)
                </insert>
        	</mapper>
        	
 10、在mybatis-config.xml文件中扫描所有接口
 			    <mappers>
                    <!--扫描指定包下面的所有mapper接口-->
                    <package name="org.java.dao"></package>
                </mappers>
                
11、在org.java.util包中,编写MyBatisUtil类,用于连接数据库
        public class MyBatisUtil {
        //用于执行对数据库的所有操作(相当于jdbc中的connection)
        private static SqlSession sqlSession;
        //编写静态块,初始sqlsession
        static {

            try {
                //创建输入流,用于读取主配置文件mybatis-config.xml
                InputStream in= Resources.getResourceAsStream("mybatis_config.xml");
                //创建一个SqlSessionFactoryBuilder构建器
                SqlSessionFactoryBuilder db=new SqlSessionFactoryBuilder();
                //创建SqlSessionFactory用于产生sqlsession
                SqlSessionFactory factory=db.build(in);
                //产生sqlsesion
                sqlSession=factory.openSession();
                //关闭流
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public  static  SqlSession getSqlSession(){
            return  sqlSession;
        }
    }
    
  
  
 12、编写业务层service
 		userService---它负责调用mapper接口的方法实现具体的操作
 		
        public class userService {
            public  void add(userInfo user){
                //获得sqlSession
                SqlSession sqlSession= MyBatisUtil.getSqlSession();
                //通过sqlsession获得mapper接口
            userMapper  mapper=sqlSession.getMapper(userMapper.class);
                //通过mapper接口对数据库进行操作
                mapper.add(user);
                //如果是增删改操作,必须要进行事务提交(commit)
                sqlSession.commit();
                //关闭sqlsession
                sqlSession.close();
            }
        }
        
        
     
13、编写测试类demo
       public class userDemo {
            userService service=new userService();
            public static void main(String[] args) {
                new userDemo().add();
            }
            private void add() {
                //创建一个用户对象
                userInfo user=new userInfo();
                user.setName("lwj");
                user.setPwd("123");
                //执行操作
                service.add(user);
            }
        }
		

123

不能直接org.java.dao创建

//必须:org–>java–>dao分开创建

//另外:org/java/dao这样创建也可以

image-20230530152448763

第二章

1、mybatis基本步骤

1、创建工程
2、导入依赖
3、导入db.properties
4、编写主配置文件mybatis-config.xml
5、编写实体类
6、编写Mapper接口
	命名规范是:实体类的名称Mapper
	例如:InfMapper
7、在resources目录下,编写Mapper.xml文件,封装对inf表操作的各种sql
	特别注意:InfMapper.xml文件的配置必须放在resources目录下,并且要与 InfMapper接口所在包名一致,而且要注意,包的目录 
	要分别创建,不能一起创建

8、在mybatais-config.xml文件配置扫描,扫描所有的mapper接口
    <mappers>
        <package name="org.java.dao"/>
    </mappers>

9、编写MyBatisUtil工具类

	@@@注意:我们在编写工具类时,使用sqlSession时没有提示的原因是因为idea12021的版本在pom.xml文件中导入依赖后,需要
	@@@手动刷新才能加入依赖

10、编写InfService业务类,用于执行各种增删改查

11、编写Demo测试类

2、导入log4j日志

@@@@每一次对mybatis操作后,控制台没有提示,我们看不到底层执行的sql语句,调试错误不方便,为了解决该问题,我们可以导入
@@@log4j日志

解决办法:导入log4j日志,对数据库的每一个操作,都会显示对应的sql语句,方便调试错误 

1、导入2个依赖
	1、log4j
	2、cglib-nodep

	    <dependency>
	      <groupId>log4j</groupId>
	      <artifactId>log4j</artifactId>
	      <version>1.2.17</version>
	    </dependency>
	    <dependency>
	      <groupId>cglib</groupId>
	      <artifactId>cglib-nodep</artifactId>
	      <version>2.1_3</version>
	    </dependency>

2、将log4j.properties日志文件导入到resources目录下即可

3、使用lombok注解

lombok的作用:
    简化实体类,自动生成get,set, toString,equals这些方法,也可以生成带参数以及不带参数的构造方法,让实体类的可读性更好

使用步骤:

1、导入lombok的依赖

	<!--    导入lombok的依赖-->
	    <dependency>
	      <groupId>org.projectlombok</groupId>
	      <artifactId>lombok</artifactId>
	      <version>1.18.24</version>
	    </dependency>

2、在实体类中使用注解生成对应的方法
	
	@Data-------该注解自动生成set,get,toString,equals方法

	@AllArgsConstructor---------自动生成带参数的构造方法
	
	@NoArgsConstructor----------自动生成无参的构造方法

	@Getter---------------------生成get方法
	
	@Setter---------------------生成set方法

@@@@注意:要使用lombok注解时,需要在idea中安装一个lombok的插件

4、mapper.xml文件详情

1、parameterType属性
parameterType:它用于指定参数类型

情况1:如果参数是一个实体对象,占位符的名称必须是实体对象中的某一个属性

  @@@  #{xxx} 它用于指定参数占位符
    <insert id="add" parameterType="org.java.entity.Inf">
        insert into inf values(null,#{name},#{score})
    </insert>


情况2:如果参数是一个具体的数据类型,占位符的名称可以任意指定(但建议尽量与属性名一致,增强代码的可读性)
    <delete id="del" parameterType="int">
        delete from inf where id=#{id}
    </delete>


情况3:如果参数是一个Map集合,占位符的名称需要与map中的键对应即可
    <insert id="add2" parameterType="map">
        insert into inf values(null,#{myname},#{myscore})
    </insert>


	parameterType="map"--------此代码,表示参数是一个Map集合
  parameterType:可以省略
2、resultType属性
resultType:它用于指定查询到的【一条数据】应该封装成什么数据类型进行返回 

	   最终是返回一个对象还是一个集合并不是由它决定,而是由查询到的数据总数决定
	   它只是负责指定查询到的每一条记录,应该封装成什么类型


    <select id="findAll" resultType="org.java.entity.Inf">
        select * from inf
    </select>
    		查询全部数据,每一条数据封装成一个Inf对象,放入到List集合中



    <select id="findById" parameterType="int" resultType="org.java.entity.Inf">
        select * from inf where id=#{id}
    </select>
    		根据条件,查询一条数据,将这一条数据转换成Inf对象返回 

手动封装类型

<!--采取映射的方式,来解决数据表与属性名不同导致取不导致的问题
        id:唯一标识
        type:映射的类型
    -->
    <resultMap id="userResultMap" type="userInfo">
      <!--column:数据库的字段名;property:实体类的属性名-->
      
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="pwd" property="pwd"/>
        <result column="regtime" property="registerTime"/>
    </resultMap>
    
********************使用
    <!--查询  使用resultMap属性替换之前的resultType属性-->
    <select id="selectAll" resultMap="userResultMap">
       select * from  user
    </select>

5、对实体包进行扫描

@@@@默认情况下,mapper.xml文件如果参数是一个实体对象或者是返回类型是一个实体对象,都要指定实体类的全路径,但这样太繁琐

解决方案:
	在mybatis-config.xml的typeAliases部分中,对实体类所在的包进行扫描,指定别名即可

	    <typeAliases>
		<package name="org.java.enty"/>
	    </typeAliases>
	    	  此代码用于对当前org.java.enty包中的实体类生成别名,名称为类名的首字母小写
		  例如:类名:Inf
		  		别名:inf

//设置此项配置后,就不用输入全路径了
配置之前: <select resultType="org.java.entity.Inf"></select>
配置之后: <select resultType="Inf"></select>

6、SQL语句中的占位符及转义符

    <!--根据id查询-->
    <!--参数占位符:
            1、#{}:会将其替换为 ?,为了防止SQL注入
            2、${}:拼sql,会存在SQL注入问题
            3、使用时机:
                参数传递的时候:#{}
                表名或者列名不固定的情况下:${}
         参数类型:
             parameterType:可以省略、
         特殊字符:
            1、转义字符:< == &lt;    字符少使用
            2、CDATA区:<![CDATA[    字符多使用
                          <
                       ]]>
        -->

    <select id="selectId" parameterType="int" resultMap="userResultMap">
      select * from  user where id=#{id}
    </select>

7、接口方法包含多个参数

	如果要接口的方法要包含多个参数,就需要采用注解,并且在mapper.xml不需要指定parameterType属性,语句中的占位符的名称 
	必须是注解参数的别名

	public void add3(@Param("name") String name,@Param("score") int score);


	    <insert id="add3">
		insert into inf values(null,#{name},#{score})
	    </insert>

8、resultMap手动封装

如果要将查询到的一条记录封装成一个具体的实体对象,要求:数据表中的字段必须要与类中属性名一致才可以

@@@@@@@@resultType:这种方式是自动封装返回类型

	它用于指定查询到的一条记录要封装成什么数据类型

	这种方式要求:数据表中查询出来的字段名必须要与类中的属性名一致才能封装
	

@@@@@@@@resultMap:这种方式用于手动封装返回类型

	它用于指定查询到的一条记录要封装成什么数据类型

	这种方式必须要自己指定将哪一个字段赋值给类中的哪一个属性(即使属性名不一致,也是可以封装的)

【问题:字段名与属性名不一致要封装对象,两种解决办法】

1、手动封装解决

方案1:用resultMap手动封装返回类型

	    <resultMap id="infMap" type="inf">
		<id column="tb_id" property="id"/>
		<result column="tb_name" property="name"/>
		<result column="tb_score" property="score"/>
	    </resultMap>

	    <select id="findAll2" resultMap="infMap">
		select * from inf2
	    </select>
2、起别名解决
方式2:给字段名指定别名即可(更简单)

        <select id="findAll2" resultType="inf">
            select tb_id id,tb_name name,tb_score score from inf2
        </select>
3、resultMap与resultType的区别
答:使用resultType是自动封装返回类型,但这种方式无法封装多表关联查询后产生的关联属性

    使用resultMap是手动封装返回类型,这种方式可以封装多表关联查询后产生的关联属性

	
    @@@如果是封装单表查询结果,没有关联属性时,一般使用resultType

    @@@如果是封装多表查询结果,有关联属性时,一般使用resultMap

9、查询

1、按成绩范围查询
	    <select id="findByScore" resultType="inf" parameterType="int">
		select * from inf where score>=#{score} order by score desc
	    </select>
	查询分数大于等于指定分数的学生

【问题:部分符号要转义】

	注意:在xml文件中,<符号不能直接作为运算符使用,系统会把它当作一个标签的开始
	小于符号必须要转义才能使用
	<     &lt;
	<=    &lt;=
	
	    <select id="findByScore" resultType="inf" parameterType="int">
		select * from inf where score &lt;=#{score} order by score desc
	    </select>
2、区间查询
    <select id="findByScoreBetween" resultType="inf">
        select * from inf where score between #{begin} and #{end} order by score desc
    </select>
3、模糊查询

    <select id="findByName" parameterType="String" resultType="inf">
        select * from inf where name like concat('%',#{name},'%')
    </select>
4、多条件查询(不确定有几个查询条件)
 <select id="findByCondition" parameterType="inf" resultType="inf">
        select * from inf
        <where>
            <if test="id!=null">
                and id=#{id}
            </if>
            <if test="name!=null and name!=''">
                and name like concat('%',#{name},'%')
            </if>
            <if test="score!=null">
                and score>=#{score}
            </if>
        </where>
        order by score desc
    </select>
5、条件查询的参数接受方式
    /*条件查询--参数接受
            1、散装参数:如果方法中有多个参数,需要使用@Param(“SQL参数占位符名称)
            2、对象参数
            3、map集合参数
      */
    //1、散装参数
   List<userInfo>  selectCondition(@Param("id") int id,@Param("name") String name);
   //2、对象参数
   List<userInfo>  selectCondition2(userInfo user);
    //3、map参数参数
    List<userInfo> selectCondition3(Map map);
散装参数的接收
    private  void selectCondition(int id,String name){//多条件查询
        //1、采用注解的方式多条件查询
        //处理参数,因为是模糊查询,需要将字符串两边加上%号
        String resteName="%"+name+"%";
        //执行sql语句并输出
        System.out.println(service.selectCondition(id,resteName));
    }

对象参数的接收
    
    private  void selectCondition2(int id,String name){//多条件查询
        //2、封装对象来多条件查询
        //处理参数,因为是模糊查询,需要将字符串两边加上%号
        String resteName="%"+name+"%";
        //封装对象
        userInfo user=new userInfo();
        user.setId(id);
        user.setName(resteName);
        //执行sql语句并输出
      System.out.println(service.selectCondition2(user));

    }
集合参数的接收
    private  void selectCondition3(String name){//多条件查询
        //3、封装集合来多条件查询
        String resteName="%"+name+"%";
        //封装集合
        Map map=new HashMap();
//        map.put("id",id);
        map.put("name",resteName);
        //执行sql语句并输出
        for (userInfo userInfo : service.selectCondition3(map)) {
            System.out.println(userInfo);
        }

    }
6、分页查询
    <!--    查询总条数-->
    <select id="getCount" resultType="integer">
        select count(*) from user
    </select>
<!--    分页查询-->
    <select id="findPage" resultMap="userResultMap">
        select  * from USER  limit #{startIndex},#{rows}
    </select>



=======================传参数
    List<userInfo> findPage(@Param("startIndex") int startIndex,@Param("rows") int rows);
	注解的意思就是:指定在SQL语句中参数名的值

10、动态sql查询

@SelectProvider(type= sqlutils.class,method = "rolequery")
<!--多条件查询  动态sql
   *if:条件判断
          test:逻辑表达式
   *问题:
      where判断时有的参数有值,有的参数没有值,就会产生sql语句报错
   *解决:
        1、恒等式  where 1=1
        2、<where> 替换 where关键字
 -->

示例:

	//用<where> 替换 where关键字
    <select id="selectCondition" resultMap="userResultMap">
        select * from user
        <where>
            <if test="id!=null">
                and id=#{id}
            </if>
            <if test="name!=null and name!=''">
                and name like #{name}
            </if>
        </where>

    </select>

单条件查询

image-20230601163012105

11、添加

    <!--添加-->
    <insert id="add" parameterType="userInfo">
        insert  into  user values(null,#{name},#{pwd},null)
    </insert>

主键返回

//添加两个属性之后,就可以获得刚刚添加到数据库的主键id

useGeneratedKeys="true"

 keyProperty="id"

获得主键id

    private void add() {//添加
        //创建一个用户对象
        userInfo user=new userInfo();
        user.setName("bulus");
        user.setPwd("111");
        //执行操作
        service.add(user);
        //获得刚刚添加的主键id
        System.out.println(user.getId());
    }

12、修改

1、修改全部字段

userMapper.xml文件

    <!--修改 此时是修改全部字段-->
    <update id="update"  parameterType="userInfo">
        update user
        set name=#{name},
            pwd=#{pwd}

        where id=#{id}
    </update>

编写接口userService.java

int update(userInfo user);//修改

编写userService.java

    public Integer update(userInfo user) {

        int count=mapper.update(user);
        //如果是增删改操作,必须要进行事务提交(commit)
        sqlSession.commit();
        //关闭sqlsession
        sqlSession.close();
        return count;
    }

执行操作

    private void update(int id,String name,String pwd) {//修改
        //创建一个用户对象
        userInfo user=new userInfo();
        user.setName(name);
        user.setPwd(pwd);
        user.setId(id);
        //执行操作
        System.out.println(service.update(user));

    }
2、动态修改字段
//只需要修改sql语句

 <update id="update"  parameterType="userInfo">
        update user
        <set>
            <if test="name!=null and name!=''">
                name=#{name},
            </if>
            <if test="pwd!=null and pwd!=''">
                pwd=#{pwd},
            </if>
        </set>
        where id=#{id}
    </update>

13、删除

1、删除一个
    <!--删除-->
    <delete id="del" >
       DELETE FROM user WHERE id = #{id}
    </delete>
2、批量删除
    <!--批量删除  如果不使用注解 ,那么collection=“array”-->
    <delete id="delIds">
          DELETE FROM user WHERE id
          in
        <foreach collection="ids" item="id" separator="," open="(" close=" )">
            #{id}
        </foreach>
    </delete>

编写接口

    //使用注解,ids代表传进来的数组
    void delIds(@Param("ids") int[] ids);//批量删除

编写service

    public void delIds(int[] ids) {
        mapper.delIds(ids);
        //如果是增删改操作,必须要进行事务提交(commit)
        sqlSession.commit();
        //关闭sqlsession
        sqlSession.close();

    }

执行操作

    private  void delIds(){//批量删除

      int[] ids={3,4,7};

      service.delIds(ids);

    }

第三章

1、mybatis基本语法

2、mybatis的关联查询

1、基本语法

1、代码片段
在编写mapper.xml文件时,公共代码可以抽取出来,形成一个代码片段,避免出现重复代码


<!--    代码片段-->
    <sql id="ConditionOne">
        <where>
            <if test="id!=null and id!=0">
                and id=#{id}
            </if>
            <if test="name!=null and name!=''">
                and name like #{name}
            </if>
        </where>
    </sql>
    
   
   
使用片段********************************
        select count(*) from user
        <include refid="ConditionOne"></include>

2、返回类型

查询的一条数据可以封装成一个实体对象返回,也可以封装一个map集合返回
	
	**一般在单表操作时,查询到的一条记录封装成实体类返回,可读性更好
	**一般在多表连接时,可以把查询到的一条记录封装成map返回,更方便

示例:联表查询返回map集合

user表:存储用户名和密码
particulars表:存放用户详细信息

xml语句

    <!--    根据id进行多表查询-->
    <select id="findById"  resultType="map">
        select  a.name,a.pwd,b.gender,b.age,b.tel,b.email,b.address  from user a,particulars b where  a.id=b.uid and a.id=#{id}
    </select>

返回一个map对象

image-20230602165237063

3、插件

在刚才的练习中,为了对user表进行操作,我们进行了如下操作
	
	1、编写了user类,自己编写了类中的属性
	2、编写了userMapper接口,自己编写了接口的方法
	3、编写了userMapper.xml,自己编写了Mapper.xml文件中的语句

【问题】:如果有100张表,我们还有一一创建吗?

【解决】:我们一般使用mybatis插件直接生成代码

	

image-20230602170604633

1、使用步骤
1、准备mybatis插件的配置文件及jar
2、修改generatorConfig.xml的配置
       <?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE generatorConfiguration  
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"  
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">  
<generatorConfiguration>  
<!-- 数据库驱动-->  
    <classPathEntry  location="mysql-connector-java-5.1.37-bin.jar"/>  
    <context id="DB2Tables"  targetRuntime="MyBatis3">  
        <commentGenerator>  
            <property name="suppressDate" value="true"/>  
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->  
            <property name="suppressAllComments" value="true"/>  
        </commentGenerator>  
        <!--数据库链接URL,用户名、密码 -->  
        <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/ajaxinfo" userId="root" password="123456">  
        </jdbcConnection>  
        <javaTypeResolver>  
            <property name="forceBigDecimals" value="false"/>  
        </javaTypeResolver>  
        <!-- 生成模型entity的包名和位置-->  
        <javaModelGenerator targetPackage="org.java.entity" targetProject="F:\D118MavenFile\Item\maven_02\src\main\java">  
            <property name="enableSubPackages" value="true"/>  
            <property name="trimStrings" value="true"/>  
        </javaModelGenerator>  
        <!-- 生成映射文件的包名和位置-->  
        <sqlMapGenerator targetPackage="org.java.dao" targetProject="F:\D118MavenFile\Item\maven_02\src\main\resources">  
            <property name="enableSubPackages" value="true"/>  
        </sqlMapGenerator>  
        <!-- 生成DAO的包名和位置-->  
        <javaClientGenerator type="XMLMAPPER" targetPackage="org.java.dao" targetProject="F:\D118MavenFile\Item\maven_02\src\main\java">  
            <property name="enableSubPackages" value="true"/>  
        </javaClientGenerator>  
        <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->  
        <table tableName="%"  enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
    </context>  
</generatorConfiguration>  
3、通过cmd进入当前目录,执行下列命令生成代码
	java -jar mybatis-generator-core-1.3.2.jar -configfile generatorConfig.xml -overwrite

4、mybatis的关联查询

数据库中的表如果存在关联,通过mybatis可以进行关联查询
	
mybatis中的关联结构主要有四种:
	1、一对多
		ag:省份与城市-----一个省份包含多个城市
	2、多对一
		ag:多个城市隶属于同一个省份
	3、一对一
		ag:人员与身份证----一个人对应一个身份证
	4、多对多
		ag:学生与老师----一个老师可以教多个学生
						 一个学生也可以被多个老师教

通过mybatis的关联查询,可以在查询一个对象时,同时将与它相关联的对象同时查询出来
1、一对多以及多对一
一般如果数据表之间存在主外键关联,就可以配置成一对多以及多对一的关联

【省份表】(主键表)

CREATE TABLE province
(
	pid INT PRIMARY KEY AUTO_INCREMENT, #省份编号
	pname VARCHAR(20) #省份名称
);
INSERT INTO province VALUES(1,'湖北省');
INSERT INTO province VALUES(2,'广东省');

【城市表】(外键表)

CREATE TABLE city
(
	cid INT PRIMARY KEY AUTO_INCREMENT,#城市编号
	cname VARCHAR(20),#城市名称
	pid INT,#城市所属省份编号
	FOREIGN KEY (pid) REFERENCES province(pid) #外键,关联到省份表的主键
)
INSERT INTO city VALUES(1,'武汉市',1);
INSERT INTO city VALUES(2,'襄阳市',1);
INSERT INTO city VALUES(3,'广州市',2);

SELECT  * FROM province;
SELECT * FROM city;
实体类
如果两个实体对象之间有关联关系:
	在一的一边,将增加一个集合类型的关联属性,集合中放所有的外键对象
	在多的一边,外键字段将会变成它对应的主键表所对应的实体类型
province表
	pid-------省份编号(主键)
	pname-----省份名称

city表
	cid--------城市编号(主键)
	cname------城市名称
	pid--------外键(关联省份)
	
Province类(一)
	pid
	pname
	
	//关联属性
	List<City> cites = new ArrayList<>();

City类(多)
	cid
	cname
	
	//关联属性
	Province province;

如果希望在java目录中使用junit,只需要改个范围

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>compile</scope>
    </dependency>
注意
在执行关联查询时要注意
	resultType:用于自动封装返回类型,只能查询到数据表中有对应的属性,无法查询关联属性
	resultMap:用于手动封装返回类型,这种方式可以加载相关属性
1、多对一的关联查询
 查询城市时,同时查询出与它关联的省份

cityMapper.xml文件

*****************************二次查询
<!--  编写二次查询,传递一个pid查询一个省份对象-->
  <select id="findProvinceByPid" parameterType="int" resultType="province">
    select * from province where  pid=#{pid}
  </select>
 
*****************************手动封装返回类型
 	<!--  封装返回关联属性-->
  <resultMap id="propResultMap" type="City">
	<!--  主键字段-->
    <id column="cid" property="cid"  />
	<!--  普通字段-->
    <result column="pid" property="pid" />
    <result column="cname" property="cname" />
	<!-- 关联属性
        多对一以及一对一的关联属性,使用association进行配置
        一对多以及多对多的关联属性,使用collection进行配置
        select="要查询的语句"
 	-->
    <association property="province" column="pid" select="findProvinceByPid" />
  	</resultMap>
  
*********************************sql片段
  <sql id="Base_Column_List" >
    cid, pid, cname
  </sql>
  
 *********************************查询语句
   <select id="selectByPrimaryKey"  resultMap="propResultMap" >
    select
 		 <include refid="Base_Column_List" />
    from city
   		 where cid = #{cid,jdbcType=INTEGER}
  </select>

image-20230605120947022

2、一对多的关联查询
查询省份时,同时查询该省份管辖的所有城市

ProvinceMapper.xml文件

*****************************二次查询
<!--  编写二次查询,传递一个pid查询一个省份对象-->
  <select id="findByPid" resultType="city">
    select  * from city where  pid=#{pid}
  </select>
 
*****************************手动封装返回类型
  <resultMap id="propResultMap" type="province">
    <id column="pid" property="pid" />
    <result column="pname" property="pname"/>
	<!--关联属性-->
    <collection property="list" column="pid" select="findByPid"/>
  </resultMap>
  
*********************************sql片段
 <sql id="Base_Column_List" >
    pid, pname
  </sql>
  
 *********************************查询语句
  <select id="selectByPrimaryKey" resultMap="propResultMap"  >
    select 
    	<include refid="Base_Column_List" />
    from province
   		 where pid = #{pid}
  </select>

image-20230605140455239

默认情况下,在mybatis中如果查询了数据库,将会显示对应的sql语句
如果在配置文件中,配置了关联属性,在查询时,会默认查询两次数据库

【问题】假设有1个主贴,这个主贴有1000个回贴
		现在我们只想看主贴时,由于配置了关联属性,当查询主贴时,系统会把这1000个回贴也查询出来,很浪费资源
		
【期望结果】查询主贴时,只查看主贴,需要用到回贴时再查询回贴,如果不查看回帖就不要进行二次查询

【解决方案】配置‘延迟加载’
		 指:关联属性一开始并不加载,什么时候用关联属性,什么时候就进行二次查询,不用就不查询
3、延迟加载

在mybatis-config.xml文件配置延迟加载

lazy:懒惰、延迟


    <!-- 引用属性文件 -->
    <properties resource="jdbc.properties"/>
    
	************开始****************
    <!--配置延迟加载机制-->
    <settings>
        <!--启用延迟加载机制-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--不使用积极加载(什么时候使用关联属性,什么时候查询关联表)-->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
	************结束****************
	
    <!-- 配置别名  -->
    <typeAliases>
        <!--扫码实体层的所有实体类-->
        <package name="org.java.entity"></package>
    </typeAliases>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flutter笔记:Widgets Easier组件库(5)使用加减器

Flutter笔记 Widgets Easier组件库&#xff08;5&#xff09;&#xff1a;使用加减器 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress…

【校招】校园招聘中的签约环节,面完HR后的流程(意向书,offer选择与三方协议)

【校招】校园招聘中的签约环节&#xff0c;面完HR后的流程&#xff08;意向书&#xff0c;offer选择与三方协议&#xff09; 文章目录 一、面完HR后的流程1、口头oc、谈薪&#xff08;两个电话&#xff09;2、邮件意向书、带薪offer&#xff08;两封邮件&#xff09;3、签三方&…

算法训练营第十三天 | LeetCode 239 滑动窗口最大值、LeetCode 347 前K个高频元素

LeetCode 239 滑动窗口最大值 本体初始思路是这样的&#xff0c;首先看下给定数组长度和维持一个滑动窗口所需要花费的时间复杂度之间的关系。初步判断是还行的&#xff0c;当然后面被样例打脸了。需要更新成优先队列的解法。原本的解法能通过37/51和46/51的测试用例。但这还不…

基于Spring Boot的校园疫情防控系统设计与实现

基于Spring Boot的校园疫情防控系统设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 管理员登录首页界面图&#xff0c;管理员进入校园疫…

AI大模型探索之路-训练篇10:大语言模型Transformer库-Tokenizer组件实践

系列篇章&#x1f4a5; AI大模型探索之路-训练篇1&#xff1a;大语言模型微调基础认知 AI大模型探索之路-训练篇2&#xff1a;大语言模型预训练基础认知 AI大模型探索之路-训练篇3&#xff1a;大语言模型全景解读 AI大模型探索之路-训练篇4&#xff1a;大语言模型训练数据集概…

msmpi 高性能并行计算 移植并行细胞自动机报错

报错情况如图 代码来源 元胞自动机生命游戏C语言并行实现 – OmegaXYZ 稍微修改&#xff0c;因为相对路径在 msmpi 10.1.1 中失效 Microsoft Windows [版本 10.0.22000.2538] (c) Microsoft Corporation。保留所有权利。C:\Users\ASUS>mpiexec -n 9 "C:\Users\ASUS\D…

四信数字孪生水库解决方案,加快构建现代化水库运行管理矩阵

近年&#xff0c;水利部先后出台《关于加快构建现代化水库运行管理矩阵的指导意见》与《构建现代化水库运行管理矩阵先行先试工作方案》等文件&#xff0c;明确总体要求及试点水库、先行区域建设技术要求等&#xff0c;为全面推进现代化水库运行管理矩阵建设工作提供依据。 《2…

自定义Maven项目模板Archetype,快速创建模板项目。

自定义Archetype 创建好模板项目&#xff0c;在项目根目录执行命令对模板做出响应调整将模板安装到本地、远程仓库使用自定义模板 创建好模板项目&#xff0c;在项目根目录执行命令 mvn archetype:create-from-project对模板做出响应调整 如果是多模块项目&#xff0c;可能需…

【数据结构】:链表的带环问题

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;数据结构 &#x1f337;追光的人&#xff0c;终会万丈光芒 前言&#xff1a; 链表的带环问题在链表中是一类比较难的问题&#xff0c;它对我们的思维有一个比较高的要求&#xff0c;但是这一类…

【模板】前缀和

原题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 前缀和模板题。 前缀和中数组下标为1~n。 前缀和&#xff1a;pre[i]pre[i-1]a[i]; 某段区间 [l,r]的和&#xff1a;pre[r]-pre[l-1] 3.…

【C语言】atoi和atof函数的使用

人生应该树立目标&#xff0c;否则你的精力会白白浪费。&#x1f493;&#x1f493;&#x1f493; 目录 •&#x1f319;知识回顾 &#x1f34b;知识点一&#xff1a;atoi函数的使用和实现 • &#x1f330;1.函数介绍 • &#x1f330;2.代码演示 • &#x1f330;3.atoi函数的…

【高校科研前沿】云南大学陈峰研究员联合多家单位在Sci. Bull发文揭示了明末特大干旱背景下北京降水变化及其以太平洋海温变化为主导的驱动新机制

文章简介 论文名称&#xff1a;Coupled Pacific Rim megadroughts contributed to the fall of the Ming Dynasty’s capital in 1644 CE&#xff08;环太平洋地区的特大干旱影响了公元 1644 年明朝的灭亡&#xff09; 第一作者及通讯作者&#xff1a;陈峰研究员&王涛研究…

38-4 Web应用防火墙 - WAF的使用及规则

准备:38-3 Web应用防火墙 - 安装配置WAF-CSDN博客 WAF的使用 启动 Nginx /usr/local/nginx/sbin/nginx 为了测试未启动 ModSecurity 时的访问效果,我们可以模拟攻击。要查看当前虚拟机的 IP 地址,可以使用命令 ifconfig 浏览器中访问ip,如果要在真实机中访问就需要关闭…

Linux 学习 --- 编辑 vi 命令

1、vi 基本概念&#xff08;了解&#xff09; 基本上 vi 可以分为三种状态&#xff0c;分别是命令模式 (command mode)、插入模式 (Insert mode) 和底行模式 (last line mode)&#xff0c;各模式的功能区分如下: 命令行模式 command mode&#xff09;  控制屏幕光标的移动&a…

c3 笔记7 css基本语法

相关内容&#xff1a;字体、段落、词间距、文字效果&#xff08;对齐、上下标、阴影&#xff09;、背景图、背景渐变、…… 单位pt与px的差别pt是印刷使用的字号单位&#xff0c;不管屏幕分辨率是多少&#xff0c;打印到纸上看起来都是相同的&#xff0c;lot的长度是0.01384英寸…

[PS小技能学习]抠图和切图

详情见视频教程&#xff1a;PS小技巧--抠图与切图 今天我们来学习如何使用PS对表情包合辑进行抠图和裁剪保存 1、首先&#xff0c;将图片导入&#xff0c;双击图层新建一个图层 2、然后点击工具栏的魔棒工具&#xff0c;再点击顶部菜单栏的添加到选区 3、点击图片的空白区域即…

《QT实用小工具·五十一》带动画的 CheckBox

1、概述 源码放在文章末尾 该项目实现了带动画效果的多选框&#xff0c;鼠标放在上面或者选中都会呈现炫酷的动画效果&#xff0c;demo演示如下&#xff1a; 项目部分代码如下所示&#xff1a; #ifndef LINEARCHECKBOX_H #define LINEARCHECKBOX_H#include <QCheckBox> …

C/C++不定参函数使用

C语言中不定参函数的使用和访问 例子 例如&#xff0c;这里想写一个打印的函数&#xff0c;但是参数并不确定该怎么办呢&#xff0c;这就要用到不定参函数 #include<stdarg.h> void printNum(int count,...){va_list ap;va_start(ap,count);//获取指定参数的起始地址&…

【CTF Reverse】XCTF GFSJ0492 insanity Writeup(反汇编+字符串搜索)

insanity 菜鸡觉得前面的题目太难了&#xff0c;来个简单的缓一下 解法 拖进 Exeinfo PE 中分析。 -> Compiler : GCC: (Debian 4.4.7-2) 4.4.7用 IDA 打开。 按 shift F12 打开 String 页面。找到 flag。 Flag 9447{This_is_a_flag}声明 本博客上发布的所有关于网络攻…

Java创建并遍历N叉树(前序遍历)

力扣 title589&#xff1a;N叉树的前序遍历 给定一个 n 叉树的根节点 root &#xff0c;返回 其节点值的 前序遍历 。 n 叉树 在输入中按层序遍历进行序列化表示&#xff0c;每组子节点由空值 null 分隔&#xff08;请参见示例&#xff09;。 思路&#xff1a; 1.初始化时…