Mybatis学习笔记(三)

十、MyBatis的逆向工程

(一)逆向工程介绍

        MyBatis的一个主要的特点就是需要程序员自己编写sql,那么如果表太多的话,难免会很麻烦,所以mybatis官方提供了一个逆向工程,可以针对单表自动生成mybatis执行所需要的代码(包括mapper.xml、mapper.java、po..)。一般在开发中,常用的逆向工程方式是通过数据库的表生成代码。

(二)构建项目环境

1.构建maven工程
2.编写配置框架配置文件

(三)逆向工程实现

1.配置generator.xml

官网配置如下:

        MyBatis Generator Core – MyBatis Generator XML Configuration File Reference

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration><context id="DB2Tables"  targetRuntime="MyBatis3"><commentGenerator><!-- 是否去除自动生成的注释 --><property name="suppressAllComments" value="true"/><!-- 生成注释是否带时间戳--><property name="suppressDate" value="true"/><!-- 生成的Java文件的编码格式 --><property name="javaFileEncoding" value="utf-8"/><!-- 格式化java代码--><property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter" /><!-- 格式化XML代码--><property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter" /></commentGenerator><!-- 数据库连接驱动类,URL,用户名、密码 --><jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://localhost:3306/mybatisdatabase100?rewriteBatchedStatements=true&amp;characterEncoding=utf8&amp;zeroDateTimeBehavior=convertToNull&amp;useSSL=false&amp;allowMultiQueries=true"userId="root" password="123456"></jdbcConnection><!-- java类型处理器:处理DB中的类型到Java中的类型 --><javaTypeResolver type="org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl"><!-- 是否有效识别DB中的BigDecimal类型 --><property name="forceBigDecimals" value="true"/></javaTypeResolver><!-- 生成实体类的位置 --><javaModelGenerator targetPackage="com.jn.entity" targetProject=".\src\main\java"><!-- 在targetPackage的基础上,根据数据库的schema再生成一层package,最终生成的类放在这个package下,默认为false --><property name="enableSubPackages" value="true"/><!-- 设置是否在getter方法中,对String类型字段调用trim()方法--><property name="trimStrings" value="true"/></javaModelGenerator><!-- 生成xml映射文件:包名(targetPackage)、位置(targetProject) --><sqlMapGenerator targetPackage="com.jn.mapper" targetProject=".\src\main\java"><property name="enableSubPackages" value="true"/></sqlMapGenerator><!-- 生成DAO接口:包名(targetPackage)、位置(targetProject) --><javaClientGenerator type="XMLMAPPER" targetPackage="com.jn.mapper" targetProject="./src/main/java"><property name="enableSubPackages" value="false"/></javaClientGenerator><!-- 要生成的表:tableName - 数据库中的表名或视图名,domainObjectName - 实体类名 --><table tableName="users"></table></context>
</generatorConfiguration>
2.添加插件 
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.jn</groupId><artifactId>MybatisProject04</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.11</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.4.2</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency></dependencies><build><resources><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources><plugins><!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 --><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.0</version><!-- 插件的依赖 --><dependencies><!-- 逆向工程的核心依赖 --><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.3.2</version></dependency><!-- 数据库连接池 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.2</version></dependency><!-- MySQL驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency></dependencies><configuration><configurationFile>C:\Users\20665\IdeaProjects\frame\MybatisProject04\generatorConfig.xml</configurationFile></configuration></plugin></plugins></build></project>
3.逆向工程生成

        在pom.xml里面添加完逆向工程的依赖以及插件之后, 按照下图所示的方式双击进行项目构建 

        也可以使用官方的API文档添加

package com.jn;import org.junit.Test;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;import java.io.File;
import java.util.List;public class GeneratorTest {//调用官方的api实现逆向工程@Testpublic void testGenerator() throws Exception{List<String> warnings = null;boolean overwrite = true;File configFile = new File("C:\\Users\\20665\\IdeaProjects\\frame\\MybatisProject04\\generatorConfig.xml");ConfigurationParser cp = new ConfigurationParser(warnings);Configuration config = cp.parseConfiguration(configFile);DefaultShellCallback callback = new DefaultShellCallback(overwrite);MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);myBatisGenerator.generate(null);}
}

        然后就自动生成了配置文件指定的数据库表的实体类 

4.测试

        在进行测试之前,先对生成的实体类进行toString重写 

package com.jn;import com.jn.entity.Users;
import com.jn.entity.UsersExample;
import com.jn.mapper.UsersMapper;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.jn.utils.MyBatisUtils;import java.util.Date;public class UserTest {//添加用户测试@Testpublic void addUser(){SqlSession sqlSession = MyBatisUtils.getSession();UsersMapper mapper = sqlSession.getMapper(UsersMapper.class);Users users = new Users();users.setName("王五");users.setAge(20);users.setGender("男");users.setBirthday(new Date());mapper.insert(users);sqlSession.commit();MyBatisUtils.close(sqlSession);System.out.println("添加成功");}//部分添加测试@Testpublic void addUserSelective(){SqlSession sqlSession = MyBatisUtils.getSession();UsersMapper mapper = sqlSession.getMapper(UsersMapper.class);Users users = new Users();users.setName("王十");users.setAge(20);mapper.insertSelective(users);sqlSession.commit();MyBatisUtils.close(sqlSession);}//根据id查询@Testpublic void selectById(){SqlSession sqlSession = MyBatisUtils.getSession();UsersMapper mapper = sqlSession.getMapper(UsersMapper.class);Users users = mapper.selectByPrimaryKey(1);System.out.println(users);MyBatisUtils.close(sqlSession);}//根据id和名称查询@Testpublic void selectByExample(){SqlSession sqlSession = MyBatisUtils.getSession();UsersMapper mapper = sqlSession.getMapper(UsersMapper.class);UsersExample example = new UsersExample();example.createCriteria().andNameEqualTo("王五");System.out.println(mapper.selectByExample(example));MyBatisUtils.close(sqlSession);}//根据id删除user@Testpublic void deleteById(){SqlSession sqlSession = MyBatisUtils.getSession();UsersMapper mapper = sqlSession.getMapper(UsersMapper.class);mapper.deleteByPrimaryKey(23);sqlSession.commit();MyBatisUtils.close(sqlSession);System.out.println("删除成功");}//根据id进行修改@Testpublic void updateById(){SqlSession sqlSession = MyBatisUtils.getSession();UsersMapper mapper = sqlSession.getMapper(UsersMapper.class);Users users = new Users();users.setId(22);users.setName("任我行");users.setAge(20);users.setGender("男");users.setBirthday(new Date());mapper.updateByPrimaryKey(users);sqlSession.commit();MyBatisUtils.close(sqlSession);System.out.println("修改成功");}}

 十一、Mybatis 缓存

(一)缓存简介

        缓存是存在于内存中的临时数据,使用缓存的目的是减少和数据库的交互次数,提高执行效率。像大多数的持久化框架一样,Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能,Mybatis 中缓存分为一级缓存,二级缓存。

(二)一级缓存

1.一级缓存介绍

        mybatis一级缓存一种是SESSION级别的,针对同一个会话SqlSession中,执行多次条件完全相同的同一个sql,那么会共享这一缓存。

2.一级缓存结构图

3.持久层 Dao 

    //根据id查询数据,测试一级缓存public User findById(Integer id);

4.编写用户持久层映射文件

    <!--根据id查询数据,测试一级缓存--><select id="findById" parameterType="int" resultType="User">select * from users where id = #{id}</select>

5.编写测试方法

    //测试一级缓存@Testpublic void testCache() throws  Exception{//获取sqlSession对象SqlSession sqlSession = MyBatisUtils.getSession();UserDao userDao = sqlSession.getMapper(UserDao.class);//第一次查询数据User user1 = userDao.findById(1);System.out.println(user1);//第二次查询数据User user2 = userDao.findById(1);System.out.println(user2);sqlSession.close();}

6.一级缓存的分析

        从上面的代码可以出,我们写了两次查询操作,但在访问数据时,只有一次。第一次先从一级缓存中获取,因为session是新创建的,一级缓存中没有数据,于是就查询数据获取数据,然后把查询的数据放到一级缓存中,此时一定要注意的是,一级缓存是一个Map集合,map的key是你的查询条件字符串,值就是查询出来的对象。等第二次查询时,先从一缓存中获取,因为上一次查询后已经放到一级缓存中了,所以从一级缓存中获取到了,就不用访问数据库了,减少和数据次的一次交互,提高了执行效率。

7.clearCache

        在测试的过程中加入清除缓存的指令 sqlSession.clearCache();

    //测试一级缓存@Testpublic void testCache() throws  Exception{//获取sqlSession对象SqlSession sqlSession = MyBatisUtils.getSession();UserDao userDao = sqlSession.getMapper(UserDao.class);//第一次查询数据User user1 = userDao.findById(1);System.out.println(user1);sqlSession.clearCache();//第二次查询数据User user2 = userDao.findById(1);System.out.println(user2);sqlSession.close();}

        查看结果:

         进行了两次的数据库查询操作

8.CRUD

        当我们在两次查询之间做增、删、改操作都会把一级缓存清空,因为不清空就不能保证缓存中的数据与数据库中数据的一致性,可能会读取不正确的数据。
        

    //测试一级缓存@Testpublic void testCache() throws  Exception{//获取sqlSession对象SqlSession sqlSession = MyBatisUtils.getSession();UserDao userDao = sqlSession.getMapper(UserDao.class);//第一次查询数据User user1 = userDao.findById(1);System.out.println(user1);//清除缓存的方式一 sqlSession.clearCache();//清除缓存的方式二,在两次查询数据之间进行增删改——更新数据User user3 = new User("岳灵珊", 28, "女", new Date());userDao.updateBatchUser(user3);sqlSession.commit();//第二次查询数据User user2 = userDao.findById(1);System.out.println(user2);sqlSession.close();}

 然后也是进行了两次的数据库查询操作

(三)二级缓存

1.二级缓存简介

        二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。

2.二级缓存结构图

3.二级缓存的开启与关闭
3.1SqlMapConfig.xml 开启二级缓存

        因为 cacheEnabled 的取值默认就为  true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为false 代表不开启二级缓存。

<!--开启二级缓存的支持--><settings><setting name="cacheEnable" value="true"/></settings>
3.2Mapper 映射文件
    <!--开启二级缓存的支持--><cache></cache>
3.3配置 useCache 属性

        将 UserDao.xml 映射文件中的<select>标签中设置 useCache=”true”代表当前这个 statement 要使用二级缓存,如果不使用二级缓存可以设置为 false。
注意:针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存。

    <!--根据id查询数据,测试一级缓存--><select id="findById" parameterType="int" resultType="User" useCache="true">select * from users where id = #{id}</select>
3.4二级缓存测试
        3..4.1出现错误 

        说是user实体类不能被序列化 

        3.4.2User序列化
public class User implements java.io.Serializable{
}
        3.4.3测试 

        经过上面的测试,我们发现执行了两次查询,并且在执行第一次查询后,我们关闭了一级缓存,再去执行第二次查询时,我们发现并没有对数据库发出 sql 语句,所以此时的数据就只能是来自于我们所说的二级缓存。

 、MyBatis分页插件

(一)分页插件的介绍

        分页是一种将所有数据分段展示给用户的技术.用户每次看到的不是全部数据,而是其中的一部分,如果在其中没有找到自己想要的内容,用户可以通过制定页码或是翻页的方式转换可见内容,直到找到自己想要的内容为止。
        分页的的好处:
        1.提高性能,一次查20个,比一次查20000个性能肯定更好;另外如果数据量很大,一次性将内容都查询出来,查询出来的结果是放在内存存里面的,会增加cpu的开销造成内存的浪费,效率极低。
        2.展现层面的考虑:如果一次展现太多的数据,不管是排版,还是美观上都不好。

(二)分页插件的引入和配置

        1.pom.xml引入插件

        <!--分页插件--><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.3.0</version></dependency>


        2.核心配置文件

    <!--插件配置——分页插件--><plugins><plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin></plugins>

(三)定义接口方法getInfo

    //分页查询public void getInfo();

(四)配置sql语句对应接口方法

    <!--分页查询--><select id="getInfo" resultType="User">select * from users</select>

(五)测试分页插件作用

    //测试分页查询@Testpublic void testPage() throws  Exception{PageHelper.startPage(1,5);SqlSession sqlSession = MyBatisUtils.getSession();UserDao userDao = sqlSession.getMapper(UserDao.class);List<User> userList = userDao.getInfo();PageInfo<User> pageInfo = new PageInfo<>(userList);List<User> uList = pageInfo.getList();int totalCount = (int) pageInfo.getTotal();int pageNum = pageInfo.getPageNum();System.out.println("总记录数:"+totalCount);System.out.println("当前页码:"+pageNum);uList.forEach(user -> System.out.println(user));sqlSession.close();MyBatisUtils.close(sqlSession);}

十三、MyBatis的注解开发

(一)注解开发介绍

        注解提供了一种简单的方式来实现简单映射语句,而不会引入大量的开销。能够读懂别人写的代码,特别是框架相关的代码。本来可能需要很多配置文件,需要很多逻辑才能实现的内容,就可以使用一个或者多个注解来替代,这样就使得编程更加简洁,代码更加清晰。

(二)常用注解介绍

        这几年来注解开发越来越流行,Mybatis 也可以使用注解开发方式,这样我们就可以减少编写 Mapper 映射文件了。
@Insert:实现新增
@Update:实现更新
@Delete:实现删除
@Select:实现查询
@Result:实现结果集封装
@Results:可以与@Result 一起使用,封装多个结果集
@ResultMap:实现引用@Results 定义的封装
@One:实现一对一结果集封装
@Many:实现一对多结果集封装
@SelectProvider: 实现动态 SQL 映射
@CacheNamespace:实现注解二级缓存的使用

(三)项目环境搭建

(四)注解实现基本CRUD

1.编写实体类

package com.jn.entity;public class Workers {private Integer id;private String name;private String age;private String gender;public Workers() {}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public Workers(Integer id, String name, String age, String gender) {this.id = id;this.name = name;this.age = age;this.gender = gender;}public Workers(String name, String age, String gender) {this.name = name;this.age = age;this.gender = gender;}@Overridepublic String toString() {return "Workers{" +"id=" + id +", name='" + name + '\'' +", age='" + age + '\'' +", gender='" + gender + '\'' +'}';}
}

2.注解开发持久层接口

package com.jn.dao;import com.jn.entity.Workers;
import org.apache.ibatis.annotations.*;import java.util.List;public interface WorkerMapper {//插入数据@Insert("insert into worker(w_name,w_age,w_gender) values(#{name},#{age},#{gender})") int insertWorker(Workers worker);//更新数据@Update("update worker set w_name=#{name},w_age=#{age},w_gender=#{gender} where w_id=#{id}")Workers updateWorker(Workers worker);//删除数据@Update("delete from worker where w_id=#{id}")int deleteWorker(Integer id);//根据id查询数据@Select("select * from worker where w_id=#{id}")@Results({@Result(column = "w_id",property = "id"),@Result(column = "w_name",property = "name"),@Result(column = "w_age",property = "age"),@Result(column = "w_gender",property = "gender")})Workers selectWorkerById(Integer id);//查询所有数据@Select("select * from worker")@Results({@Result(column = "w_id",property = "id"),@Result(column = "w_name",property = "name"),@Result(column = "w_age",property = "age"),@Result(column = "w_gender",property = "gender")})public List<Workers> selectAllWorker();
}

3.编写测试方法

package com.jn;import com.jn.dao.WorkerMapper;
import com.jn.entity.Workers;
import com.jn.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;public class WorkerTest {//插入数据测试@Testpublic void insertWorker(){SqlSession sqlSession = MyBatisUtils.getSession();WorkerMapper mapper = sqlSession.getMapper(WorkerMapper.class);Workers worker = new Workers("小明", "18", "男");int i = mapper.insertWorker(worker);sqlSession.commit();MyBatisUtils.close(sqlSession);System.out.println(i+"添加成功");}//更新数据@Testpublic void updateWorker(){SqlSession sqlSession = MyBatisUtils.getSession();WorkerMapper mapper = sqlSession.getMapper(WorkerMapper.class);Workers worker = new Workers(1,"张飞", "18", "女");int i = mapper.updateWorker(worker);sqlSession.commit();MyBatisUtils.close(sqlSession);System.out.println(i+"修改成功");}//删除数据@Testpublic void deleteWorker(){SqlSession sqlSession = MyBatisUtils.getSession();WorkerMapper mapper = sqlSession.getMapper(WorkerMapper.class);int i = mapper.deleteWorker(2);sqlSession.commit();MyBatisUtils.close(sqlSession);System.out.println(i+"删除成功");}//根据id查找数据@Testpublic void selectWorkerById(){SqlSession sqlSession = MyBatisUtils.getSession();WorkerMapper mapper = sqlSession.getMapper(WorkerMapper.class);Workers worker = mapper.selectWorkerById(1);System.out.println(worker);MyBatisUtils.close(sqlSession);}//查看所有数据@Testpublic void selectAllWorker(){SqlSession sqlSession = MyBatisUtils.getSession();WorkerMapper mapper = sqlSession.getMapper(WorkerMapper.class);for (Workers worker : mapper.selectAllWorker()) {System.out.println(worker);}MyBatisUtils.close(sqlSession);}
}

(五)使用注解实现复杂关系映射

1.复杂关系注解介绍

@Results  注解
        代替的是标签<resultMap>
        该注解中可以使用单个@Result 注解,也可以使用@Result 集合
        @Results({@Result(),@Result()})或@Results(@Result())
@Resutl 注解
        代替了 <id> 标签和<result> 标签
        属性介绍:
                id 是否是主键字段
                column 数据库的列名
                property 需要装配的属性名
                one 需要使用的@One 注解(@Result(one=@One)()))
                many 需要使用的@Many 注解(@Result(many=@many)()))
@One  注解(一对一)
        代替了<assocation> 标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。
        属性介绍:
                select 指定用的 来多表查询的 sqlmapper
                fetchType 会覆盖全局的配置参数 lazyLoadingEnabled。
        使用格式:
                @Result(column=" ",property="",one=@One(select=""))
@Many  注解(多对一)
        代替了<Collection> 标签, 是是多表查询的关键,在注解中用来指定子查询返回对象集合。
        注意:聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType(一般为 ArrayList)但是注解中可以不定义;
        使用格式:
                @Result(property="",column="",many=@Many(select=""))

2.一对一复杂关系映射

  2.1实体类添加
package com.jn.entity;public class Person {private Integer id;private String name;private Idcard idcard;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Idcard getIdcard() {return idcard;}public void setIdcard(Idcard idcard) {this.idcard = idcard;}@Overridepublic String toString() {return "Person{" +"id=" + id +", name='" + name + '\'' +", idcard=" + idcard +'}';}
}
package com.jn.entity;import java.beans.Introspector;
import java.util.Date;public class Idcard {private Integer id;private String cardno;private Date uselife;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getCardno() {return cardno;}public void setCardno(String cardno) {this.cardno = cardno;}public Date getUselife() {return uselife;}public void setUselife(Date uselife) {this.uselife = uselife;}
}
  2.2IdCard持久层接口
package com.jn.dao;import com.jn.entity.Idcard;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;public interface IdCardMapper {@Select("select * from idcard where c_id=#{id}")@Results({@Result(column = "c_id",property = "id"),@Result(column = "c_cardno",property = "cardno"),@Result(column = "c_uselife",property = "uselife")})public Idcard findById(Integer id);
}
  2.3Person持久层接口
package com.jn.dao;import com.jn.entity.Idcard;
import com.jn.entity.Person;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;public interface PersonMapper {@Select("select * from person where p_id=#{id}")@Results({@Result(column = "p_id", property = "id"),@Result(column = "p_name", property = "name"),@Result(column = "p_id",property= "idcard",javaType = Idcard.class,one = @One(select="com.jn.dao.IdCardMapper.findById"))})public Person findById(Integer id);
}
  2.4测试

 

package com.jn;import com.jn.dao.PersonMapper;
import com.jn.entity.Idcard;
import com.jn.entity.Person;
import com.jn.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;public class PersonTest {@Testpublic void test1(){SqlSession session= MyBatisUtils.getSession();PersonMapper mapper=session.getMapper(PersonMapper.class);Person person=mapper.findById(1);System.out.println(person);MyBatisUtils.close(session);}
}

3.使用注解实现一对多复杂关系映射

3.1实体类构建
package com.jn.entity;public class Employee {private Integer id;private String name;private String gender;private String age;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}@Overridepublic String toString() {return "Employee{" +"id=" + id +", name='" + name + '\'' +", gender='" + gender + '\'' +", age='" + age + '\'' +'}';}
}
package com.jn.entity;public class Department {private Integer id;private String name;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
3.2Department加入 List
package com.jn.entity;import java.util.List;public class Department {private Integer id;private String name;private List<Employee> employeeList;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<Employee> getEmployeeList() {return employeeList;}public void setEmployeeList(List<Employee> employeeList) {this.employeeList = employeeList;}@Overridepublic String toString() {return "Department{" +"id=" + id +", name='" + name + '\'' +", employeeList=" + employeeList +'}';}
}
3.3EmployeeMapper
package com.jn.dao;import com.jn.entity.Department;
import com.jn.entity.Employee;
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 java.util.List;public interface EmployeeMapper {@Select("select * from employee where e_depart_id=#{id}")@Results({@Result(column = "e_id",property = "id"),@Result(column = "e_name",property = "name"),@Result(column = "e_age",property = "age"),@Result(column = "e_gender",property = "gender")})public List<Employee> findById(Integer id);
}
3.4DepartmentMapper

 

package com.jn.dao;import com.jn.entity.Department;
import com.jn.entity.Employee;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;public interface DepartmentMapper {@Select("select * from department where d_id=#{id}")@Results({@Result(column = "d_id",property = "id"),@Result(column = "d_name",property = "name"),@Result(column = "d_id",property = "employeeList",many = @Many(select = "com.jn.dao.EmployeeMapper.findById"))})public Department findById(Integer id);
}
3.5测试
package com.jn;import com.jn.dao.DepartmentMapper;
import com.jn.dao.EmployeeMapper;
import com.jn.entity.Department;
import com.jn.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;public class EmployeeTest {@Testpublic void test1(){SqlSession session= MyBatisUtils.getSession();DepartmentMapper departmentMapper=session.getMapper(DepartmentMapper.class);Department department=departmentMapper.findById(1);System.out.println(department.getName());department.getEmployeeList().forEach(System.out::println);MyBatisUtils.close(session);}
}

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

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

相关文章

Github 2024-11-08Java开源项目日报 Top9

根据Github Trendings的统计,今日(2024-11-08统计)共有9个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目9Vue项目1经验丰富的Java(后端)开发人员核心面试问题和答案 | 互联网Java工程师进阶知识完全扫盲 创建周期:2085 天开发语言:Java协议…

【新闻文本分类识别】Python+CNN卷积神经网络算法+深度学习+人工智能+机器学习+文本处理

一、介绍 文本分类识别系统。本系统使用Python作为主要开发语言&#xff0c;首先收集了10种中文文本数据集&#xff08;“体育类”, “财经类”, “房产类”, “家居类”, “教育类”, “科技类”, “时尚类”, “时政类”, “游戏类”, “娱乐类”&#xff09;&#xff0c;然…

数据结构 ——— 链式二叉树的前中后序遍历递归实现

目录 前言 链式二叉树示意图​编辑 手搓一个链式二叉树 链式二叉树的前序遍历 链式二叉树的中序遍历 链式二叉树的后序遍历 前言 在上一章学习了链式二叉树的前中后序遍历的解析 数据结构 ——— 链式二叉树的前中后序遍历解析-CSDN博客 接下来要学习的是代码实现链式…

<项目代码>YOLOv8 pcb板缺陷检测<目标检测>

YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一个回归问题&#xff0c;能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法&#xff08;如Faster R-CNN&#xff09;&#xff0c;YOLOv8具有更高的…

yarn报错`warning ..\..\package.json: No license field`:已解决

出现这个报错有两个原因 1、项目中没有配置许可证 在项目根目录package.json添加 {"name": "next-starter","version": "1.0.0",# 添加这一行"license": "MIT", }或者配置私有防止发布到外部仓库 {"priv…

大模型学习笔记------CLIP模型解读与思考

大模型学习笔记------CLIP模型详解 1、为什么提出CLIP模型2、CLIP模型详解3、CLIP模型的意义4、一些思考 上文说到&#xff0c;多模态大模型应该是非常有发展前景的&#xff0c;首先来学习 CLIP&#xff08;Contrastive Language-Image Pretraining&#xff09;这个多模态模型…

昇思25天学习打卡营第1天|快速入门

昇思25天学习打卡营第1天|快速入门 目录 昇思25天学习打卡营第1天|快速入门实操教程 一、MindSpore内容简介 主要特点&#xff1a; MindSpore的组成部分&#xff1a; 二、入门实操步骤 1. 安装必要的依赖包 2. 下载并处理数据集 3. 构建网络模型 4. 训练模型 5. 测试…

【Python TensorFlow】入门到精通

TensorFlow 是一个开源的机器学习框架&#xff0c;由 Google 开发&#xff0c;广泛应用于机器学习和深度学习领域。本篇将详细介绍 TensorFlow 的基础知识&#xff0c;并通过一系列示例来帮助读者从入门到精通 TensorFlow 的使用。 1. TensorFlow 简介 1.1 什么是 TensorFlow…

Python 学习完基础语法知识后,如何进一步提高?

入门Python后&#xff0c;就可以拿些小案例练手了&#xff0c;这时候千万不要傻乎乎地成天啃语法书。 编程是一门实践的手艺&#xff0c;讲究孰能生巧。不管是去手撸算法、或者照葫芦画瓢写几个小游戏都可以让你的Python突飞猛进。 之前看github比较多&#xff0c;推荐给大家…

Java:数据结构-再谈String类

字符串常量池 首先我们来思考这段代码&#xff0c;为什么运行结果一个是true&#xff0c;一个是false呢&#xff1f; public class Test {public static void main(String[] args) {String s1"123";String s2"123";String s3new String("555")…

书生第四期实训营基础岛——L1G2000 玩转书生「多模态对话」与「AI搜索」产品

基础任务 MindSearch使用示例 书生浦语使用示例 书生万象使用示例 进阶任务 问题&#xff1a;目前生成式AI在学术和工业界有什么最新进展&#xff1f; 回答截图&#xff1a; 知乎回答链接&#xff1a;目前生成式AI在学术和工业界有什么最新进展&#xff1f;

ReactPress:重塑内容管理的未来

ReactPress Github项目地址&#xff1a;https://github.com/fecommunity/reactpress 欢迎提出宝贵的建议&#xff0c;欢迎一起共建&#xff0c;感谢Star。 ReactPress&#xff1a;重塑内容管理的未来 在当今信息爆炸的时代&#xff0c;一个高效、易用的内容管理系统&#xff0…

短视频矩阵系统源码/抖去推源头技术4年开发

#短视频矩阵系统# #短视频矩阵系统源码# #短视频矩阵系统源码开发# #短视频矩阵系统源头技术开发# 抖音短视频矩阵系统集成开发是指利用抖音平台的开放接口和API&#xff0c;构建一个系统&#xff0c;该系统能够管理多个抖音矩阵账号&#xff0c;实现内容的统一发布、账号管理、…

CJ/T188-2004 报文举例

CJ/T188-2004 报文举例 # 读水表地址 # 请求报文&#xff1a; FE FE FE FE 68 AA AA AA AA AA AA AA AA 03 03 81 0A 00 49 16FE FE FE FE &#xff1a;前导字符 FE68 &#xff1a;起始字符AA &#xff1a;仪表类型AA AA AA AA AA AA AA &#xff1a;仪表地址&#xff08;当…

JavaEE进阶---第一个SprintBoot项目创建过程我的感受

文章目录 1.我的创建感受2.环境配置说明2.1xml文件国内源2.2配置流程 3.创建项目4.项目创建说明5.第一个程序--helloworld 1.我的创建感受 今天是学习这个spring boot项目创建的一天&#xff0c;这个确实过程坎坷&#xff0c;于是我自己决定弄一个这个IDEA的 专业版本&#xf…

7.1、实验一:RIPv1配置

一、源文件 7.1、实验一&#xff1a;RIPv1配置: https://url02.ctfile.com/d/61945102-63657205-d343fe?p2707 (访问密码: 2707) 二、实验目的 学会配置RIPv1路由 查看和调试RIPv1路由协议相关信息 三、实验要求 1.拓扑图 2. 四、开始实验 1.配置ip 配置R1 配置R2 配置…

【ARM Linux 系统稳定性分析入门及渐进 1.3 -- Crash工具编译过程】

文章目录 Build Procedure安装二进制 RPM从源代码重建构建过程从 tar 映像构建ARM 平台 Crash 工具安装从源 RPM 构建Build Procedure 从 RHEL3 版本开始,如果在系统安装时选择了开发工具包集(Development Tools),crash 工具会自动安装。然而,对于其他内核版本,或者如果…

【2023工业图像异常检测文献】GRAD: 基于异常生成和重权密集对比模式的异常检测方法

Generating and Reweighting Dense Contrastive Patterns for Unsupervised Anomaly Detection 1、Background 图像异常检测在各个领域扮演着至关重要的角色&#xff0c;包括工业产品缺陷检测、医学图像病变检测、使用X光图像的安全检查以及视频监控。 然而&#xff0c;由于无…

计算机毕业设计Hadoop+Spark大模型微博情感分析 微博舆情分析 微博爬虫 微博可视化 微博大数据分析 微博大数据 大数据毕业设计 Hive数据仓库

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

原型设计软件Axure RP 11 现已发布,更快、更实用的原型设计丨附下载

Axure RP是一套专门为网站或应用程序所设计的快速原型设计工具&#xff0c; 可以让应用网站策划人员或网站功能界面设计师更加快速方便的建立Web AP和Website的线框图、流程图、原型和规格。Axure RP 11&#xff08;下载试用&#xff09; 现已发布&#xff0c;更快、更实用的原…