MyBatis3.4全集笔记
MyBatis
1. MyBatis 简介
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
MyBatis虽然改变了名字,但是实际的内核还是ibatis
MyBatis以高轻量级闻名于全球,提出以注入SQL的方式来管理持久化,让整个项目在数据库操作这块与SQL语言完全解耦,所以深受开发人员的喜爱
mybatis是一款高轻量级的基于ORM(对象关系映射)半自动化的持久层框架,它更加关注原生sql的编写,在实际开发过程中能够实现sql语句与业务代码的完全的解耦。它还支持强大的sql查询、存储过程、高级映射、缓存机制。还支持强大的基于OGNL动态sql的编写。
2. Maven MyBatis搭建
基础脚手架效果如图:

需要配置的几项内容:
(1).pom文件
(2).mybatis.xml文件
(3).pojo类
(4).数据库映射XML
(5).创建数据库操作对应的接口
(6).控制器
第一项,配置pom文件,需要加入两个maven包,一个是数据库连接驱动,一个是mybatis
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.31</version>
</dependency>
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.6</version>
</dependency>
第二项,添加mybatis.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><settings><!--当返回行的所有列都是空时,MyBatis默认返回null--><setting name="returnInstanceForEmptyRow" value="true"/><!--显示sql语句-->
<setting name="logImpl" value="STDOUT_LOGGING"/></settings><environments default="development"><environment id="development"><!--使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域--><transactionManager type="JDBC"/><!-- mybatis提供了3种数据源类型,分别是:POOLED,UNPOOLED,JNDI --><!-- POOLED 表示支持JDBC数据源连接池 --><!-- UNPOOLED 表示不支持数据源连接池 --><!-- JNDI 表示支持外部数据源连接池 --><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/gxa"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><mappers><!-- 映射文件方式1,一个一个的配置<mapper resource="cn/thinknovo/pojo/UserMapper.xml"/>--><!-- 映射文件方式2,自动扫描包内的Mapper接口与配置文件 --><package name="cn/thinknovo/pojo"/></mappers>
</configuration>
第三项,pojo类,创建一个类名与数据库相同,属性名和数据库字段名相同的pojo对象。
第四项,数据库映射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">
<!-- namespace一般定义为 包名+类名 -->
<mapper namespace="cn.thinknovo.pojo.UserMapper"><select id="selectUser" resultType="cn.thinknovo.pojo.User">select * from user;</select><insert id="insertUser" parameterType="cn.thinknovo.pojo.User">insert into user values (#{id},#{username},#{password});</insert>
</mapper>
第五项,定义数据库操作接口,这里需要注意的是,mybatis以此接口为调用入口,通过此接口对应的方法来检查并对应mapper.xml文件中的增删改查
public interface UserMapper {// 方法名、参数类型、返回类型要和mapper.xml文件中的id相同List<User> selectUser();void insertUser(User user);
}
第六项,创建控制器–测试
public class MybatisConsole {public static void main(String[] args) {try {Reader reader = Resources.getResourceAsReader("mybatis.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);SqlSession session = sqlSessionFactory.openSession();UserMapper userMapper = session.getMapper(UserMapper.class);List<User> userList = userMapper.selectUser();System.out.println(userList);session.close();} catch (IOException e) {e.printStackTrace();}}
}
至此,基础脚手架搭建完成
3. Mapper.xml文件的注册和自动扫描
在mybatis.xml文件中,可以直接使用package的方式来完成自动扫描,这样以后就不需要一个个的添加mapper.xml文件了
<mappers><!-- 映射文件方式1,一个一个的配置<mapper resource="cn/thinknovo/pojo/UserMapper.xml"/>--><!-- 映射文件方式2,自动扫描包内的Mapper接口与配置文件 --><package name="cn/thinknovo/pojo"/></mappers>
4.解决后台提示找不到对应xml文件
Idea默认找不到对应的xml配置路径,在pom文件的build标签中,加入resource标签如下代码:
<resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource>
</resources>
5.两种处理操作数据库的方式
(1).通过session得到对应的Mapper接口对象,然后由此对象调用对应的操作方法,例如:
Reader reader = Resources.getResourceAsReader("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sqlSessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
List<User> userList = userMapper.selectUser();
System.out.println(userList);
(2).通过session直接调用接口中对应的操作方法
// 第一个参数对应接口中的方法名
session.selectList("selectUser");
(PS:注意在这里接口文件和Mapper.xml文件是必须的,缺一不可,可以通过删除对应的文件来测试执行结果。)
6.关闭自动提交事务

这里注意,只有执行增、删、改的时候,才需要提交事务,查询是不需要事务的,在操作完对应的增删改之后,执行session.commit();
PS:注意,mybatis默认事务就关闭了自动提交,可以通过接口查看

7.Xml配置方式的增删改查
首先配置mapper.xml文件
<!-- namespace一般定义为 包名+文件名 -->
<mapper namespace="cn.thinknovo.pojo.UserMapper"><select id="selectUser" resultType="cn.thinknovo.pojo.User">select * from user;
</select><insert id="insertUser" parameterType="cn.thinknovo.pojo.User">insert into user values (#{id},#{username},#{password});
</insert><update id="updateUser" parameterType="cn.thinknovo.pojo.User">update user set username=#{username},password=#{password} where id=#{id};
</update><delete id="deleteUser" parameterType="java.lang.String">delete from user where id=#{id};
</delete>
</mapper>
然后在修改接口代码
public interface UserMapper {// 方法名、参数类型、返回类型要和mapper.xml文件中的id相同List<User> selectUser();void insertUser(User user);void updateUser(User user);void deleteUser(String id);
}
在控制器中调用接口中指定的四个方法,就可以完成基本的增删改查
在控制器中调用接口中指定的四个方法,就可以完成基本的增删改查
8.多参数传递
在项目中,多参数传递更多的是基于pojo对象,或者map结构传递,但是也可能有需要多个形式参数传递,比如这样:
UserMapper.insertUserByPassword("think12345","54321");
这种情况,配置文件需要做对应的处理,改成下面的样子:
<insert id="insertUserByPassword" parameterType="java.lang.String">insert into user values(null,#{param1},#{param2});
</insert>
param1代表获取第一个形式参数,依次类推
param1代表获取第一个形式参数,依次类推
也可以这样:
<insert id="insertUserByPassword" parameterType="java.lang.String">insert into user values(null,#{arg0},#{arg1});
</insert>
arg0代表获取第一个形式参数,依次类推
arg0代表获取第一个形式参数,依次类推
如果有更多的这样的形式参数,就递增数字,比如第三个就是parma3或者arg2,在动态配置sql的时候,根据需要可以任意调换顺序,比如可以换成下面的效果:
<insert id="insertUserByPassword" parameterType="java.lang.String">insert into user values(null,#{arg1},#{arg0});
</insert>
arg0还是代表第一个参数,arg1还是代表第二个参数,不受影响。
arg0还是代表第一个参数,arg1还是代表第二个参数,不受影响。
还可以这样写:
在接口中声明方法
/**
* mybatis 把参数转换为 map 了,其中@Param("key") 参数内
容就是 map 的 value
* @param name
* @param pwd
* @return
*/
List<User> selByNamePwd(@Param("name") String
userName,@Param("pwd") String userPwd);
在 mapper.xml 中添加
#{} 里面写@Param(“内容”)参数中内容
<!-- 当多参数时,不需要写 parameterType -->
<select id=" selByNamePwd" resultType="User" >
select * from User where name=#{name} and pwd=#{pwd}
</select>
9.Java中的Map结构传递
如果在项目中需要多参数传递,更建议大家使用java.util.map的结构传递,这也是大部分项目使用的方式,mybatis会根据key来对应获取value值,设置的传递类型还是parameterType,比如这样:
<insert id="insertUserByUserAndPassword" parameterType="map">
insert into user values(null,#{username},#{password});
</insert>
10.Map结构传递
如果要定义为map结构传递,需要在mybatis.xml中定义map的结构方式,比如这样:
<parameterMap id="userMap" type="cn.thinknovo.pojos.User"><parameter property="username" javaType="java.lang.String"/><parameter property="password" javaType="java.lang.String"/>
</parameterMap>
这里的id就是map引入的名字,我们在传递参数类型设定为map以后就可以使用,比如:
<insert id="insertUserByUserAndPassword2" parameterMap="userMap" >
insert into user values(null,#{username},#{password});
</insert>
11.注解的使用
删除mapper.xml文件,然后在接口文件中通过注解的方式添加sql语句
public interface UserMapper {
// 方法名、参数类型、返回类型要和mapper.xml文件中的id相同
@Select("select * from user")
List<User> selectUser();
@Insert("insert into user values (#{id},#{username},#{password})")
void insertUser(User user);
@Update("update user set username=#{username},password=#{password} where id=#{id}")
void updateUser(User user);
@Delete("delete from user where id=#{id}")
void deleteUser(String id);
}
注意,我们现在可以删除mybatis.xml中的mapper标签,我们也可以在mybatis.xml文件中添加的mapper标签,不再需要resource属性,而是class属性,如下:
<!-- 在配置文件中 关联包下的 接口类--><mappers><mapper class="c.thinknovo.mybatis3.UserMapper"/></mappers>
12.动态SQL的if使用 – 非常重要
根据不同的条件执行不同的结果
<select id="selectUser" resultType="cn.thinknovo.pojo.User" parameterType="cn.thinknovo.pojo.User">select * from user<if test="username != null">where username=#{username}</if>
</select>
在配置文件中添加动态的if语句,如果传递过来的user对象中,username不等于null,那么追加条件查询
13.动态SQL的where使用
如果我们有多个条件需要添加,但是有可能一个条件都不满足,那么这时候使用上面的方式就会出现问题,所以我们还需要在if外部添加一个where标签
<select id="selectUser" resultType="cn.thinknovo.pojo.User" parameterType="cn.thinknovo.pojo.User">select * from user<where><if test="username != null">username=#{username}</if><if test="password != null">and password=#{password}</if></where>
</select>
可以看到,where包含了两个if,而第一个if中没有and,where标签会自动检查状态,如果标签返回的第一个匹配内容是以 and或or 开头的,则会自动删除and或者or ,然后再追加where
14.动态SQL的choose when使用
<select id="selectUser" resultType="cn.thinknovo.pojo.User" parameterType="cn.thinknovo.pojo.User">select * from user where password='888888'
<where><choose><when test="username != null">AND username=#{username}</when><when test="password != null">AND password=#{password}</when><otherwise>AND id=#{id}</otherwise></choose>
<where>
</select>
Choose when 类似于java中的switch case,任中只会走一个,一般是在有一个条件固定的情况下,需要额外不确定的条件时,使用choose的方式
15.逆向工程mybatis-generator-maven-plugin
(1)首先修改pom文件为下面的内容,需要注意configurationFile标签是对应mybatis-generator的路径和文件名,修改为自己想要的,其余不做修改:
<?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>cn.thinknovo</groupId><artifactId>mybatis002</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><name>mybatis002 Maven Webapp</name><!-- FIXME change it to the project's website --><url>http://www.example.com</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.7</maven.compiler.source><maven.compiler.target>1.7</maven.compiler.target></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.46</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.6</version></dependency><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.3.6</version></dependency></dependencies><build><finalName>mybatis002</finalName><pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --><plugins><plugin><artifactId>maven-clean-plugin</artifactId><version>3.0.0</version></plugin><!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --><plugin><artifactId>maven-resources-plugin</artifactId><version>3.0.2</version></plugin><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.7.0</version></plugin><plugin><artifactId>maven-surefire-plugin</artifactId><version>2.20.1</version></plugin><plugin><artifactId>maven-war-plugin</artifactId><version>3.2.0</version></plugin><plugin><artifactId>maven-install-plugin</artifactId><version>2.5.2</version></plugin><plugin><artifactId>maven-deploy-plugin</artifactId><version>2.8.2</version></plugin> <plugin>
<!--Mybatis-generator插件,用于自动生成Mapper和POJO-->
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.6</version>
<configuration>
<!--配置文件的位置-->
<configurationFile>src\main\resources\mybatis-generator-config.xml</configurationFile>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
<executions>
<execution>
<id>Generate MyBatis Artifacts</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.6</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</pluginManagement></build>
</project>
(2)接着添加mybatis-generator-config.xml文件,注意修改
(1)classPathEntry为自己的数据库连接池jar包物理路径
(2)jdbcConnection为自己的数据库连接参数
(3)javaModelGenerator为实体类生成的位置 修改targetPackage和targetProject
(4)sqlMapGenerator为*Mapper.xml 文件的位置 修改targetPackage和targetProject
(5)javaClientGenerator为Mapper 接口文件的位置 修改targetPackage和targetProject
(6)table为表对应内容,多表就配置多个,tableName表名 domainObjectName类名
完整配置如下:
<?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> <!-- 本地数据库驱动程序jar包的全路径 -->
<classPathEntry location="C:\Users\Administrator\.m2\repository\mysql\mysql-connector-java\5.1.46\mysql-connector-java-5.1.46.jar"/> <!-- 指定mybatis版本 -->
<context id="context" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressAllComments" value="false"/>
<property name="suppressDate" value="true"/>
</commentGenerator> <!-- 数据库的相关配置 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/hiber"
userId="root"
password="thinknovo"/> <!--指定生成的类型为java类型,避免数据库中number等类型字段 -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver> <!-- 实体类生成的位置 修改targetPackage和targetProject-->
<javaModelGenerator targetPackage="cn.thinknovo.test" targetProject="src/main/java">
<property name="enableSubPackages" value="false"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator> <!-- *Mapper.xml 文件的位置 修改targetPackage和targetProject-->
<sqlMapGenerator targetPackage="cn.thinknovo.test" targetProject="src/main/java">
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator> <!-- Mapper 接口文件的位置 修改targetPackage和targetProject-->
<javaClientGenerator targetPackage="cn.thinknovo.test" targetProject="src/main/java"
type="XMLMAPPER">
<property name="enableSubPackages" value="false"/>
</javaClientGenerator> <!-- 相关表的配置 多表就配置多个 tableName表名 domainObjectName类名 --><table tableName="user" domainObjectName="User" enableCountByExample="false"enableDeleteByExample="false" enableSelectByExample="false"enableUpdateByExample="false"/></context>
</generatorConfiguration>
(3)接着在idea右上角,点击edit

(4)开始配置mybatis-generator-maven-plugin运行

(5)输入运行命令mybatis-generator:generate -e

(6)点击保存,现在可以看到一个运行方式了,点击运行就可以自动得到内容了

(7)运行生成对应的文件

16.一对一映射
类似于hibernate中的创建办法,模拟一个人员对应一个学号,创建两个pojo实体类,下面代码省略了set、get方法
(1)第一个类是Iren人员类
public class Iren {private long id;private String renyuanname;private long xuehaoid;private Ixuehao ixuehao; // 添加一个学号类的对象
(2)第二个类是Ixuehao学号类
public class Ixuehao {private long id;private String xuehao;
(3)创建一个Irenmapper.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">
<!-- namespace一般定义为 包名+文件名 -->
<mapper namespace="cn.thinknovo.mybatis.pojo.IrenMapper"><select id="selectIren" resultMap="getOneToOneMap">select t1.id,t1.renyuanname,t1.xuehaoid,t2.id,t2.xuehaofrom iren t1,ixuehao t2where t1.xuehaoid = t2.id;</select>
<resultMap id="getOneToOneMap" type="cn.thinknovo.mybatis.pojo.Iren">
<id property="id" column="id"/>
<result property="renyuanname" column="renyuanname"/>
<result property="xuehaoid" column="xuehaoid"/>
<association property="ixuehao" javaType="cn.thinknovo.mybatis.pojo.Ixuehao">
<id property="id" column="id"/>
<result property="xuehao" column="xuehao"/>
</association>
</resultMap>
</mapper>
PS:这里使用到了resultMap标签,此标签中创建一对一的映射关系,在其中的id标签代表主键,result标签代表普通字段,association标签代表映射关系类
PS:这里使用到了resultMap标签,此标签中创建一对一的映射关系,在其中的id标签代表主键,result标签代表普通字段,association标签代表映射关系类
(4)创建一个Irenmapper接口
public interface IrenMapper {List<Iren> selectIren();
}
(5)创建一个Console测试
public static void main(String[] args) {try {Reader reader = Resources.getResourceAsReader("mybatis.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);SqlSession session = sqlSessionFactory.openSession(false);IrenMapper irenMapper = session.getMapper(IrenMapper.class); List<Iren> list = irenMapper.selectIren();System.out.println(list.size());for(Iren iren : list) {System.out.println(iren.getRenyuanname());System.out.println(iren.getIxuehao().getXuehao());}session.close();} catch (IOException e) {e.printStackTrace();}
}
(6)反向一对一处理
在Ixuehao类中创建Iren的对象,然后创建对应的Ixuehao的mapper接口和xml文件,在配置resultMap时,把前面配置的两个表的参数互换,就可以实现反向一对一。
<select id="selectIxuehao" resultMap="getOneToOneMap">select t1.id,t1.renyuanname,t1.xuehaoid,t2.id,t2.xuehaofrom iren t1,ixuehao t2where t1.xuehaoid = t2.id;
</select>
<resultMap id="getOneToOneMap" type="cn.thinknovo.mybatis.pojo.Ixuehao"><id property="id" column="id"/><result property="xuehao" column="xuehao"/><association property="iren" javaType="cn.thinknovo.mybatis.pojo.Iren"><id property="id" column="id"/><result property="renyuanname" column="renyuanname"/><result property="xuehaoid" column="xuehaoid"/></association>
</resultMap>
17.一对多映射
基于班级和学生的关系建立映射,set、get方法省略
(1)第一个类是Iclass班级类
public class Iclass {private long id;private String cname;private List<Istudent> list; // 这个班级中所有的学生
(2)第二个类是Istudent学生类
public class Istudent {private long id;private String sname;private long cid;
(3)创建IclassMapper.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">
<!-- namespace一般定义为 包名+文件名 -->
<mapper namespace="cn.thinknovo.mybatis.pojo.IclassMapper"><select id="selectIclass" resultMap="getOneToManyMap">select t1.id,t1.cname,t2.id id2,t2.sname,t2.cidfrom iclass t1,istudent t2where t1.id = t2.cid and t1.id=4;</select> <resultMap id="getOneToManyMap" type="cn.thinknovo.mybatis.pojo.Iclass">
<id property="id" column="id"/>
<result property="cname" column="cname"/>
<collection property="list" ofType="cn.thinknovo.mybatis.pojo.Istudent">
<id property="id" column="id2"/>
<result property="sname" column="sname"/>
<result property="cid" column="cid"/>
</collection>
</resultMap>
</mapper>
PS:这里注意的是,一对多使用的collection标签,并且mybatis自身bug,导致,当两张表的主键同名时,list中只有一个对象,解决这个问题的办法是把其中一个主键id改一个别名
PS:这里注意的是,一对多使用的collection标签,并且mybatis自身bug,导致,当两张表的主键同名时,list中只有一个对象,解决这个问题的办法是把其中一个主键id改一个别名


(4)创建一个Iclassmapper接口
public interface IclassMapper {Iclass selectIclass();
}
(5)创建一个Console测试
public static void main(String[] args) {try {Reader reader = Resources.getResourceAsReader("mybatis.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);SqlSession session = sqlSessionFactory.openSession(false);IclassMapper iclassMapper = session.getMapper(IclassMapper.class);Iclass iclass = iclassMapper.selectIclass();System.out.println(iclass.getCname());System.out.println(iclass.getList());for(Istudent istudent : iclass.getList()) {System.out.println(istudent.getSname());}session.close();} catch (IOException e) {e.printStackTrace();}
}
(6)反向多对一处理
在mybatis里面其实没有多对一的说法,多对一只能看做是一对一,所以我们需要在Istudent中增加Iclass对象:
public class Istudent {private long id;private String sname;private long cid;private Iclass iclass; // 增加班级对象
创建一个IstudentMapper.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">
<!-- namespace一般定义为 包名+文件名 -->
<mapper namespace="cn.thinknovo.mybatis.pojo.IstudentMapper"><select id="selectIstudent" resultMap="getOneToOneMap">select t1.id,t1.cname,t2.id id2,t2.sname,t2.cidfrom iclass t1,istudent t2where t1.id = t2.cid and t2.id=2;</select> <resultMap id="getOneToOneMap" type="cn.thinknovo.mybatis.pojo.Istudent">
<id property="id" column="id2"/>
<result property="sname" column="sname"/>
<result property="cid" column="cid"/>
<association property="iclass" javaType="cn.thinknovo.mybatis.pojo.Iclass">
<id property="id" column="id"/>
<result property="cname" column="cname"/>
</association>
</resultMap>
</mapper>
PS:这里使用到的是一对一的处理法则,所以使用的一对一的标签association
PS:这里使用到的是一对一的处理法则,所以使用的一对一的标签association
然后创建IstudentMapper接口,编写测试类完成,这里省略…
18.多对多映射
还是基于订购商品操作,一个用户可以对应多个商品,一个商品可以对应多个订单,其实在mybatis实现多对多映射操作,类似于一对多映射,只是SQL编写的相对复杂一些,因为涉及到了中间表。
(1)第一个类是Ishangpin商品的类
public class Ishangpin {private long id;private String shangpinname;private List<Igoumai> list; // list代表多个购买者
(2)第二个类是Igoumai购买者的类
public class Igoumai {private long id;private String goumainame;
(3)创建IshangpinMapper.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">
<!-- namespace一般定义为 包名+文件名 -->
<mapper namespace="cn.thinknovo.mybatis.pojo.IshangpinMapper"><select id="selectIshangpin" resultMap="getManyToManyMap">selectt1.shangpinid,t1.goumaiid,t2.id,t2.goumainame,t3.id id2,t3.shangpinnamefromidingdan t1,igoumai t2,ishangpin t3where t1.goumaiid=t2.id and t1.shangpinid=t3.id and t1.shangpinid=6;</select> <resultMap id="getManyToManyMap" type="cn.thinknovo.mybatis.pojo.Ishangpin">
<id property="id" column="id2"/>
<result property="shangpinname" column="shangpinname"/>
<collection property="list" ofType="cn.thinknovo.mybatis.pojo.Igoumai">
<id property="id" column="id"/>
<result property="goumainame" column="goumainame"/>
</collection>
</resultMap>
</mapper>
PS:这个配置文件中有多处需要注意的地方,1.查看SQL的编写,三表关联查询;2.resultMap中涉及的还是collection标签;3.两张表的id主键的名字不能相同,必须保证其中一个是别名

PS:这个配置文件中有多处需要注意的地方,1.查看SQL的编写,三表关联查询;2.resultMap中涉及的还是collection标签;3.两张表的id主键的名字不能相同,必须保证其中一个是别名
(4)创建一个IshangpinMapper接口
public interface IshangpinMapper {List<Ishangpin> selectIshangpin();
}
(5)创建一个Console测试
IshangpinMapper ishangpinMapper = session.getMapper(IshangpinMapper.class);
List<Ishangpin> list = ishangpinMapper.selectIshangpin();
System.out.println(list);
System.out.println(list.get(0).getShangpinname());
System.out.println(list.get(0).getList());
System.out.println(list.get(0).getList().get(0).getGoumainame());
(6)反向多对多处理
原理和上述一致,只需要在购买者中的增加商品的list,并且配置购买者的mapper接口和XML文件即可。
19.缓存
一级缓存SqlSession
- 应用程序和数据库交互的过程是一个相对比较耗时的过程
- 缓存存在的意义:让应用程序减少对数据库的访问,提升程序运行效率
- MyBatis 中默认 SqlSession 缓存开启
3.1 同一个 SqlSession 对象调用同一个时,只有第一次访问数据库,第一次之后把查询结果缓存到SqlSession缓存区(内存)中
3.2 缓存的是 statement 对象.(简单记忆必须是用一个是用一个),在 myabtis 时一个对应一个 statement 对象
3.3 有效范围必须是同一个 SqlSession 对象
缓存流程:
步骤一: 先去缓存区中找是否存在 statement
步骤二:返回结果
步骤三:如果没有缓存 statement 对象,去数据库获取数据
步骤四:数据库返回查询结果
步骤五:把查询结果放到对应的缓存区中
二级缓存SqlSessionFactory 缓存
有效范围:同一个 factory 内哪个 SqlSession 都可以获取
什么时候使用二级缓存:当数据频繁被使用,很少被修改
使用二级缓存步骤:
步骤一:在 mapper.xml 中添加
步骤二:如果不写 readOnly=”true”需要把实体类序列化
<cache readOnly=” true”></ cache >
步骤三:当 SqlSession 对象 close()时或 commit()时会把 SqlSession 缓存的数据刷(flush)到 SqlSessionFactory 缓存区中
ngpin();
System.out.println(list);
System.out.println(list.get(0).getShangpinname());
System.out.println(list.get(0).getList());
System.out.println(list.get(0).getList().get(0).getGoumainame());
(6)反向多对多处理
原理和上述一致,只需要在购买者中的增加商品的list,并且配置购买者的mapper接口和XML文件即可。## 缓存### 一级缓存SqlSession1. 应用程序和数据库交互的过程是一个相对比较耗时的过程
2. 缓存存在的意义:让应用程序减少对数据库的访问,提升程序运行效率
3. MyBatis 中默认 SqlSession 缓存开启
3.1 同一个 SqlSession 对象调用同一个<select>时,只有第一次访问数据库,第一次之后把查询结果缓存到SqlSession缓存区(内存)中
3.2 缓存的是 statement 对象.(简单记忆必须是用一个是用一个<select>),在 myabtis 时一个<select>对应一个 statement 对象
3.3 有效范围必须是同一个 SqlSession 对象
缓存流程:
步骤一: 先去缓存区中找是否存在 statement
步骤二:返回结果
步骤三:如果没有缓存 statement 对象,去数据库获取数据
步骤四:数据库返回查询结果
步骤五:把查询结果放到对应的缓存区中### 二级缓存SqlSessionFactory 缓存有效范围:同一个 factory 内哪个 SqlSession 都可以获取
什么时候使用二级缓存:当数据频繁被使用,很少被修改
使用二级缓存步骤:
步骤一:在 mapper.xml 中添加
步骤二:如果不写 readOnly=”true”需要把实体类序列化
<cache readOnly=” true”></ cache >
步骤三:当 SqlSession 对象 close()时或 commit()时会把 SqlSession 缓存的数据刷(flush)到 SqlSessionFactory 缓存区中相关文章:
MyBatis3.4全集笔记
MyBatis 1. MyBatis 简介 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。 iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Ja…...
IDEA一键启动多个微服务
我们在做微服务项目开发的时候,每次刚打开IDEA,就需要把各个服务一个个依次启动,特别是服务比较多时,逐个点击不仅麻烦还费时。下面来说一下如何一键启动多个微服务。 操作步骤 点击Edit Configurations 2.点击“”,…...
【Python3】random.choices 权重随机选取 详解
random.choices是Python 3中random模块中的一个函数,用于从指定的序列中以指定的权重随机选择元素。下面我将对该函数进行详细介绍,并提供一些示例代码和注意事项。 函数签名: random.choices(population, weightsNone, *, cum_weightsNone…...
【面试题-015】Redis的线程模型是什么 为什么速度快
redis面试题 Redis的线程模型是什么 为什么速度快? Redis是一个开源的、高性能的键值对(key-value)数据库。它之所以速度快,主要得益于以下几个方面的设计: 单线程模型: Redis的操作是单线程的ÿ…...
EasyV开发人员的使用说明书
在可视化大屏项目时,开发人员通常需要承担以下任务: 技术实现:根据设计师提供的设计稿,利用前端技术(如HTML、CSS、JavaScript等)和后端技术(根据具体项目需求,可能是Java、Python、…...
构造列表初始化和构造初始化区别
构造列表初始化和构造初始化在C等编程语言中,是两种不同的初始化类实例成员的方式。以下是它们之间的主要区别: 构造列表初始化(初始化列表) 定义:初始化列表以一个冒号开始,接着是一个以逗号分隔的数据成…...
Message passing mechanism (消息传递机制)
objc_msgSend 是 Objective-C 运行时系统中的一个核心函数,用于实现消息传递机制。在 Objective-C 中,方法调用实际上是消息传递的过程,当你在代码中调用一个方法时,编译器会将其转换为 objc_msgSend 函数的调用。 objc_msgSend …...
详解 Spark SQL 代码开发之数据读取和保存
一、通用操作 /** 基本语法:1.读取:SparkSession.read[.format("format")[.option("...")]].load("path")2.保存:DataFrame.write[.format("format")[.option("...")]][.mode("Save…...
Pulsar 社区周报 | No.2024-05-30 | BIGO 百页小册《Apache Pulsar 调优指南》
“ 各位热爱 Pulsar 的小伙伴们,Pulsar 社区周报更新啦!这里将记录 Pulsar 社区每周的重要更新,每周发布。 ” BIGO 百页小册《Apache Pulsar 调优指南》 Hi,Apache Pulsar 社区的小伙伴们,社区 2024 上半年度的有奖问…...
第二证券股票杠杆:4分钟直线涨停!这一赛道,AH股集体爆发!
今日早盘,A股继续小幅震动收拾,首要股指涨跌互现,两市个股跌多涨少,成交有萎缩的趋势。 盘面上,医药、中字头、旅游、房地产等板块相对活跃,混合实践、玻璃基板、AI手机PC、光刻机等板块跌幅居前。 “中字…...
JavaScript 进阶征途:解锁Function奥秘,深掘Object方法精髓
个人主页:学习前端的小z 个人专栏:JavaScript 精粹 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结,欢迎大家在评论区交流讨论! 文章目录 🈵Function方法 与 函数式编程💝1 call 💝…...
斜拉桥智慧施工数字孪生
基于图扑自主研发的 HT for Web 产品,利用现场照片及 CAD 图纸,结合 PBR 材质,搭建了具有赛博朋克风格的智慧斜拉桥可视化解决方案,精准复现斜拉桥建造规划过程,辅助运维人员对桥梁基建过程的网格化管理。提高桥梁的建…...
【chatGPT API】Function Calling:将自然语言转换为API调用或数据库查询
文章目录 一. 介绍二. 常见用例与Function Calling调用逻辑三. 调用细节1. 调用行为:tool_choice2. 调用规定:functions 四. 实战:查询公司相关产品 一. 介绍 OpenAI可以根据用户的要求输出一个符合用户要求的入参值。然后用户拿到入参值之后…...
Oracle Hint /*+APPEND*/插入性能总结
oracle append用法 Oracle中的APPEND用法主要用于提高数据插入的效率。 基本用法:在使用了APPEND选项后,插入数据会直接加到表的最后面,而不会在表的空闲块中插入数据。这种做法不需要寻找freelist中的free block,从而避免了在…...
正邦科技(day3)
出厂测试 设备校准 这个需要注意的是校准电流、电压、电感的时候有时候负感器会装反,mcu会坏,需要flash一下清空内存...
mac电脑多协议远程管理软件:Termius 8.4.0激活版下载
Termius 是一款功能强大的跨平台远程访问工具,可用于管理和连接各种远程系统和服务器。它支持SSH、Telnet、SFTP和Serial协议,并提供了键盘快捷键、自动完成和多标签功能,使用户可以方便地控制和操作远程主机。 Termius 提供了端到端的加密保…...
网络攻击的常见形式
开篇 本篇文章来自于《网络安全 ——技术与实践》的学习整理笔记。 正篇 口令窃取 相比于利用系统缺陷破坏网络系统,最容易的方法还是通过窃取用户的口令进入系统。因为人们倾向于选择很糟糕的口令作为登录密码,所以口令猜测很容易成功。通常࿰…...
ReactDOM 18版本 使用createRoot 替换render详解
概述 React 18 提供了两个 root API,被称之为 Legacy Root API 和 New Root API: Legacy Root API:是指之前版本的 root API ReactDOM.render,它将创建一个以 “legacy” 模式运行的 root,其工作方式与 React 17 完全…...
【赠书活动】好书推荐—《详解51种企业应用架构模式》
导读: 企业应用包括哪些?它们又分别有哪些架构模式?世界著名软件开发大师Martin Fowler给你答案。 01 什么是企业应用 我的职业生涯专注于企业应用,因此,这里所谈及的模式也都是关于企业应用的。(企业应用…...
SpringBoot启动时使用外置yml文件
第一步:打包时排除yml文件 <build><resources><resource><!-- 排除的文件的路径 --><directory>src/main/resources</directory><excludes><!-- 排除的文件的名称 --><exclude>application-dev.yml</e…...
实战指南:用Python的pyttsx3库打造你的专属语音助手
1. 从零认识pyttsx3:你的代码会说话 第一次听到电脑用标准播音腔朗读出我写的文字时,那种感觉就像小时候收到会说话的生日贺卡。pyttsx3这个神奇的Python库,能让任何文本通过声卡变成人声。不同于需要联网的语音合成服务,它完全离…...
别再死磕公式了!用Diffusers库5分钟搞懂Stable Diffusion的CFG引导(附代码避坑)
5分钟实战:用Diffusers库玩转Stable Diffusion的CFG参数调优 你是否曾经盯着Stable Diffusion生成的图片皱眉头——明明输入了详细的提示词,结果却像在开盲盒?别急着怀疑人生,问题可能出在那个神秘的guidance_scale参数上。今天我…...
偏振无关 宽带消色差 长波红外超透镜模型 粒子群优化算法 复现论文:2022年博士论文
偏振无关 宽带消色差 长波红外超透镜模型 粒子群优化算法 复现论文:2022年博士论文:消色差超透镜设计原理及其应用研究 论文介绍:采用各向同性的多种不同形状的超表面单元,利用庞大的数据库和粒子群优化算法,设计长波红…...
2026跨境电商数据采集避坑指南:实测实在Agent如何终结“数字员工”的幻觉时代
【摘要】 2026年3月,跨境电商行业正式迈入“Agent驱动”的生产力新纪元。随着阿里巴巴Accio Work、腾讯云MAGIC Agent 2.0等工具的密集发布,传统基于脚本的爬虫正被具备自主决策能力的“数字员工”取代。然而,在实际业务落地中,通…...
原神帧率解锁终极指南:三步轻松突破60FPS限制
原神帧率解锁终极指南:三步轻松突破60FPS限制 【免费下载链接】genshin-fps-unlock unlocks the 60 fps cap 项目地址: https://gitcode.com/gh_mirrors/ge/genshin-fps-unlock 还在为《原神》60帧限制感到困扰吗?genshin-fps-unlock是一款专为《…...
2025届学术党必备的六大降重复率平台实际效果
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 人工智能生成内容也就是AIGC普及之后,文本检测系统变得越来越精密了。为了避免机…...
2026届最火的五大降AI率网站实际效果
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 现当下各种AI检测工具正变得越发普及,要是用户所提交的文本被判定为有着高AI生成…...
车轨桥刚柔耦合仿真与 Simpack 与 Abaqus 联合仿真那些事儿
1.simpack与abaqus联合仿真教程 2.车轨桥刚柔耦合仿真教程,柔性钢轨建模,fbi文件生成,ftr文件书写 3.包括模型在工程仿真领域,车轨桥刚柔耦合仿真以及 Simpack 与 Abaqus 联合仿真都是极具实用价值的技术,今天就来给大…...
解锁AMD Ryzen全部潜力:SMUDebugTool硬件调试神器完全指南
解锁AMD Ryzen全部潜力:SMUDebugTool硬件调试神器完全指南 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https:…...
智能抢票新纪元:MaxBot如何突破票务平台限制?2025革新攻略
智能抢票新纪元:MaxBot如何突破票务平台限制?2025革新攻略 【免费下载链接】tix_bot Max搶票機器人(maxbot) help you quickly buy your tickets 项目地址: https://gitcode.com/gh_mirrors/ti/tix_bot 在数字票务时代,热门活动门票往…...
