parameterType表示传入参数的类型,官方文档有很多别名可以参考
<insert id="insertStu" parameterType="long">
insert into t_account(id,name,age,height,birth,sex)
values (null,#{name},#{age},#{height},#{birth},#{sex})
insert>
<select id="selectByAgeAndSex" resultType="student">
select * from t_student where age=#{arg0} and sex=#{arg1}
select>
/**
* 通过年龄和性别查学生
* @param age
* @param sex
* @return
*/
List<Student> selectByAgeAndSex(Integer age,Character sex);
<select id="selectByAgeAndSex" resultType="student">
select * from t_student where age=#{age} and sex=#{sex}
select>
/**
* 通过年龄和性别查学生
* @param age
* @param sex
* @return
*/
List<Student> selectByAgeAndSex(@Param("age") Integer age,@Param("sex") Character sex);
/**
* 把数据表中所有数据返回给map嵌套
* 将查询结果的id值作为整个map集合的key
* @return
*/
@MapKey("id")
Map<String,Map<String,Object>> selectByAllRetMap();
/**结果:
* {
* 1={sex=男, name=张三, birth=1980-10-11, id=1, age=20, height=1.811},
* 2={sex=女, name=李四, birth=1988-10-11, id=2, age=20, height=1.61},
* 4={sex=男, name=哇嘎, birth=2022-10-17, id=4, age=20, height=1.8},
* 5={sex=女, name=瓦西, birth=2022-10-17, id=5, age=20, height=1.86}
* }
*/
property是pojo中的属性名称
column是数据表中的字段名
<resultMap id="stuResultMap" type="student">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
<result property="height" column="height"/>
<result property="birth" column="birth"/>
<result property="sex" column="sex"/>
resultMap>
<select id="selectAllByResultMap" resultMap="stuResultMap">
select * from t_student
select>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
<select id="selectByMultiCases" resultType="car">
select * from t_car where 1=1
<if test="brand != null and brand != ''">
and brand like "%"#{brand}"%"
if>
<if test="guidePrice != null and guidePrice != ''">
and guide_price > #{guidePrice}
if>
<if test="carType != null and carType != ''">
and car_type = #{carType}
if>
select>
@Test
public void testSelectByMultiCases(){
SqlSession session = SqlSessionUtil.openSession();
CarMapper mapper = session.getMapper(CarMapper.class);
//这三个参数可以动态调整
List<Car> cars = mapper.selectByMultiCases("比亚迪", 20.0, "新能源");
cars.forEach(car -> System.out.println(car));
session.close();
}
<select id="selectByMultiCasesByTrim" resultType="car">
select * from t_car
<trim prefix="where" prefixOverrides="and|or" suffixOverrides="and|or">
<if test="brand != null and brand != ''">
and brand like "%"#{brand}"%"
if>
<if test="guidePrice != null and guidePrice != ''">
and guide_price > #{guidePrice}
if>
<if test="carType != null and carType != ''">
and car_type = #{carType}
if>
trim>
select>
<update id="updateById">
update t_car
<set>
<if test="carNum != null and carNum != ''">car_num = #{carNum},if>
<if test="brand != null and brand != ''">brand = #{brand},if>
<if test="guidePrice != null and guidePrice != ''">guide_price = #{guidePrice},if>
<if test="produceTime != null and produceTime != ''">produce_time = #{produceTime},if>
<if test="carType != null and carType != ''">car_type = #{carType},if>
set>
where id = #{id}
update>
这三个标签是在⼀起使⽤的:
<choose>
<when>when>
<when>when>
<when>when>
<otherwise>otherwise>
choose>
等同于
if(){
}else if(){
}else if(){
}else if(){
}else{
}
<select id="selectByChose" resultType="car">
select * from t_car
<where>
<choose>
<when test="brand != null and brand != ''">
brand like "%"#{brand}"%"
when>
<when test="guidePrice != null">
guide_price > 2
when>
<otherwise>
car_type = #{carType}
otherwise>
choose>
where>
select>
<delete id="deleteByIds">
delete from t_car where id in
<foreach collection="ids" separator="," open="(" close=")" item="id">
#{id}
foreach>
delete>
<insert id="insertMatch">
insert into t_car values
<foreach collection="cars" item="car" separator=",">
(null,#{car.carNum},#{car.brand},#{car.guidePrice},#{car.produceTime},#{car.carType})
foreach>
insert>
int insertMatch(@Param("cars") List<Car> cars);
sql标签⽤来声明sql⽚段
include标签⽤来将声明的sql⽚段包含到某个sql语句当中
<sql id="carCols">
id,
car_num as carNum,
brand,
guide_price as guidePrice,
produce_time as produceTime,
car_type as carType
sql>
<select id="selectAllRetMap" resultType="map">
select <include refid="carCols"/> from t_car
select>
准备数据库表:⼀个班级对应多个学⽣。班级表:t_clazz。学⽣表:t_stu
判断哪个是主表的方法:哪个在前
比如多对一就是多在前,多个学生对应一个班级,此时学生就是主表
多对一如何在jvm里解释
将学生类中添加班级类即可
left join左连接,把左边的全部查出来,右边有的则匹配,没有则为null
记得要在表后面跟上代称,如t_stu s
select s.sid,s.sname,c.cid,c.cname
from t_stu s left join t_clazz c on s.cid=c.cid
where s.sid = 1
问题:根据ID查询学生信息,并返回班级信息
<mapper namespace="com.powernode.mybatis.mapper.StuMapper">
<resultMap id="stuResultMap" type="student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<result property="clazz.cid" column="cid"/>
<result property="clazz.cname" column="cname"/>
resultMap>
<select id="selectById" resultMap="stuResultMap">
select s.sid,s.sname,s.cid,c.cname from t_stu s left join t_clazz c on s.cid=c.cid where s.sid = #{sid}
select>
mapper>
将resultMap中的类设置为Association(即另一个类)
<resultMap id="stuResultMapAssociation" type="student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<association property="clazz" column="clazz">
<id property="cid" column="cid"/>
<result property="cname" column="cname"/>
association>
resultMap>
两条SQL语句,分步查询。(这种方式常用:优点一是可复用。优点二是支持懒加载)
<resultMap id="stuResultMapStep" type="student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<association property="clazz" select="com.powernode.mybatis.mapper.ClazzMapper.selectByCid" column="cid">
<id property="cid" column="cid"/>
<result property="cname" column="cname"/>
association>
resultMap>
<select id="selectByIdStep" resultMap="stuResultMapStep">
select sid,sname,cid from t_stu where sid=#{sid}
select>
用到的时候加载,不用到的时候不加载
<association fetchType="lazy">
....
一般在mybatis-config.xml核心配置文件中设置全局懒加载选项
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
settings>
一对多:一个班级对应多个学生(班级是主表,学生是副表)
实现方法:在Clazz班级类中设置一个数组,这样可以容纳多个学生
在select中增加collection标签,表示集合
<resultMap id="clazzResultMapCollection" type="clazz">
<id property="cid" column="cid"/>
<result property="cname" column="cname"/>
<collection property="students" ofType="student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
collection>
resultMap>
<select id="selectByCidCollection" resultMap="clazzResultMapCollection">
select c.cid,c.cname,s.sid,s.sname from t_clazz c left join t_stu s on c.cid=s.cid where c.cid=#{cid}
select>
<resultMap id="clazzResultMapStep" type="clazz">
<id property="cid" column="cid"/>
<result property="cname" column="cname"/>
<collection property="students" ofType="student" select="com.powernode.mybatis.mapper.StuMapper.selectByCid" column="cid" >
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
collection>
resultMap>
<select id="selectByCidStep" resultMap="clazzResultMapStep">
select cid,cname from t_clazz where cid=#{cid}
select>
MyBatis的缓存机制:
在执行DQL(select语句)的时候,MyBatis把语句加载到jvm虚拟机中,若是下次又执行完全一样的语句,则直接从缓存中读取,若是期间执行了增删改(改动数据库)的操作则自动清空缓存,必须重新从硬盘中读取
缓存:cache
缓存的作⽤:通过减少IO的⽅式,来提⾼程序的执⾏效率。
mybatis的缓存:将select语句的查询结果放到缓存(内存)当中,下⼀次还是这条select语句的话,直接从缓存中取,不再查数据库。⼀⽅⾯是减少了IO。另⼀⽅⾯不再执⾏繁琐的查找算法。效率⼤⼤提升。
mybatis缓存包括:
⼀级缓存默认是开启的。不需要做任何配置。
原理:只要使⽤同⼀个SqlSession对象执⾏同⼀条SQL语句,就会⾛缓存。
模块名:mybatis-010-cache
@Test
public void selectById(){
SqlSession session = SqlSessionUtil.openSession();
CarMapper mapper1 = session.getMapper(CarMapper.class);
Car car1 = mapper1.selectById(20L);
System.out.println(car1);
CarMapper mapper2 = session.getMapper(CarMapper.class);
Car car2 = mapper2.selectById(20L);
System.out.println(car2);
session.close();
}
Preparing: select * from t_car where id = ?
Car{id=20, carNum=‘3001’, brand=‘比亚迪比’, guidePrice=30.0, produceTime=‘2030-01-02’, carType=‘新能源’}
Car{id=20, carNum=‘3001’, brand=‘比亚迪比’, guidePrice=30.0, produceTime=‘2030-01-02’, carType=‘新能源’}
可以发现只执行了一次sql语句,因为两句sql一样所以直接从缓存中拿
两种情况下一级缓存会失效
//执行清空缓存
session.clearCache();
⼆级缓存的范围是SqlSessionFactory。
使⽤⼆级缓存需要具备以下⼏个条件:
<setting name="cacheEnabled" value="true">
<cache />
public void selectById2() throws Exception{
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("mybatis-config.xml"));
SqlSession session1 = sessionFactory.openSession();
CarMapper mapper1 = session1.getMapper(CarMapper.class);
Car car1 = mapper1.selectById2(19L);
System.out.println(car1);
//只有当SqlSession关闭的时候,一级缓存才会到二级缓存里
session1.close();
SqlSession session2 = sessionFactory.openSession();
CarMapper mapper2 = session2.getMapper(CarMapper.class);
Car car2 = mapper2.selectById2(19L);
System.out.println(car2);
session2.close();
}
⼆级缓存的失效:只要两次查询之间出现了增删改操作。⼆级缓存就会失效。【⼀级缓存也会失效】
集成EhCache是为了代替mybatis⾃带的⼆级缓存。⼀级缓存是⽆法替代的。
mybatis对外提供了接⼝,也可以集成第三⽅的缓存组件。⽐如EhCache、Memcache等。都可以。
EhCache是Java写的。Memcache是C语⾔写的。所以mybatis集成EhCache较为常⻅,按照以下步骤操
作,就可以完成集成:
第⼀步:引⼊mybatis整合ehcache的依赖。
<dependency>
<groupId>org.mybatis.cachesgroupId>
<artifactId>mybatis-ehcacheartifactId>
<version>1.2.2version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>1.2.11version>
<scope>testscope>
dependency>
第⼆步:在类的根路径下新建echcache.xml⽂件,并提供以下配置信息
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<diskStore path="e:/ehcache"/>
<!--diskPersistent:是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false-
->
<defaultCache eternal="false" maxElementsInMemory="1000" overflowToDis
k="false" diskPersistent="false"
timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStor
eEvictionPolicy="LRU"/>
ehcache>
第三步:修改SqlMapper.xml⽂件中的标签,添加type属性。
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
逆向工程可以通过sql表自动生成pojo类、Mapper类,自动生成增删改查代码
pom中添加环境:
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-maven-pluginartifactId>
<version>1.4.1version>
<configuration>
<overwrite>trueoverwrite>
configuration>
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.30version>
dependency>
dependencies>
plugin>
plugins>
build>
新建generatorConfig.xml
DOCTYPE generatorConfiguration
PUBLIC "-//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">
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true"/>
commentGenerator>
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/powernode"
userId="root"
password="root">
jdbcConnection>
<javaModelGenerator targetPackage="com.powernode.mybatis.pojo" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true"/>
javaModelGenerator>
<sqlMapGenerator targetPackage="com.powernode.mybatis.mapper" targetProject="src/main/resources">
<property name="enableSubPackages" value="true"/>
sqlMapGenerator>
<javaClientGenerator
type="xmlMapper"
targetPackage="com.powernode.mybatis.mapper"
targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
javaClientGenerator>
<table tableName="t_car" domainObjectName="Car"/>
context>
generatorConfiguration>
public void test(){
SqlSession session = SqlSessionUtil.openSession();
CarMapper mapper = session.getMapper(CarMapper.class);
//查询一个结果
Car car = mapper.selectByPrimaryKey(20L);
System.out.println(car);
//查询所有结果
List<Car> cars = mapper.selectByExample(null);
cars.forEach(car1 -> System.out.println(car));
// 根据条件查询结果(QBC query by criteria查询风格
// 添加查询条件
CarExample carExample = new CarExample();
carExample.createCriteria()
.andBrandLike("比亚迪")
.andGuidePriceBetween(new BigDecimal(0),new BigDecimal(40));
//添加or
carExample.or().andCarTypeLike("技术车");
//最终sql语句:select * from t_car where (brand like "%比亚迪%" and guide_price>=0 and guide_price<40) or (car_type like "%技术车%")
List<Car> cars1 = mapper.selectByExample(carExample);
cars1.forEach(car1 -> System.out.println(car1));
session.close();
}
mysql的limit后面两个数字:
假设已知页码pageNum,还有每页显示的记录条数pageSize,第一个数字可以动态的获取吗?
select
*
from
tableName ......
limit
(pageNum - 1) * pageSize, pageSize
PageHelper插件可以很方便的管理和使用分页
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>5.3.1version>
dependency>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">plugin>
plugins>
@Test
public void test(){
SqlSession session = SqlSessionUtil.openSession();
CarMapper mapper = session.getMapper(CarMapper.class);
//查询第二页,前三条记录
PageHelper.startPage(2,3);
List<Car> cars = mapper.selectAll();
//查看分页信息
PageInfo<Car> pageInfo = new PageInfo<>(cars);
System.out.println(pageInfo);
session.close();
}
注解式开发适合简单的单标CRUD操作,不适合复杂操作
@Insert( "insert into t_car values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})")
int insertCar(Car car);
@Delete("delete from t_car where id=#{id}")
int deleteById(Long id);
@Update("update t_car set car_num=#{carNum},brand=#{brand},guide_price=#{guidePrice},produce_time=#{produceTime},car_type=#{carType} where id=#{id}")
int updateById(Car car);
@Select("select * from t_car where id=#{id}")
Car selectById(Long id);
@Test
public void insertCar(){
SqlSession session = SqlSessionUtil.openSession();
CarMapper mapper = session.getMapper(CarMapper.class);
Car car = new Car(null,"10377","报道33车1",35.0,"2022-12-05","技术车");
mapper.insertCar(car);
session.commit();
session.close();
}