多种方式,常见的包括三种:
pojo类Student中添加一个属性:Clazz clazz; 表示学生关联的班级对象。
package com.powernode.mybatis.pojo;
public class Student { //Student是多的一方
private Integer sid;
private String sname;
private Clazz clazz; //Clazz是一的一方
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", sname='" + sname + '\'' +
", clazz=" + clazz +
'}';
}
public Clazz getClazz() {
return clazz;
}
public void setClazz(Clazz clazz) {
this.clazz = clazz;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Student() {
}
}
package com.powernode.mybatis.mapper;
import com.powernode.mybatis.pojo.Student;
public interface StudentMapper {
/*
* @description: 根据id获取学生信息,同时获取学生关联的班级信息
* @param id
* @return 学生对象,但是学生对象当中含有班级对象
*/
Student selectById(Integer id);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.powernode.mybatis.mapper.StudentMapper">
<resultMap id="studentResultMap" 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="studentResultMap">
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 = #{sid}
select>
mapper>
package com.powernode.mybatis.test;
import com.powernode.mybatis.mapper.StudentMapper;
import com.powernode.mybatis.pojo.Student;
import com.powernode.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
public class StudentMapperTest {
@Test
public void testSelectById(){
SqlSession sqlSession = SqlSessionUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = mapper.selectById(1);
System.out.println(student);
System.out.println(student.getSid());
System.out.println(student.getSname());
System.out.println(student.getClazz().getCid());
System.out.println(student.getClazz().getCname());
sqlSession.commit();
sqlSession.close();
}
}
association翻译为:关联。
一个学生对象关联一个班级对象。
property
:提供要映射的POJO类的属性名javaType
:用来指定要映射的java类型 <resultMap id="studentResultMapAssociation" type="Student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<association property="clazz" javaType="Clazz">
<result property="cid" column="cid"/>
<result property="cname" column="cname"/>
association>
resultMap>
//一条sql语句:association
Student selectByIdAssciation(Integer id);
@Test
public void testSelectByIdAssciation(){
SqlSession sqlSession = SqlSessionUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = mapper.selectByIdAssciation(4);
System.out.println(student);
sqlSession.commit();
sqlSession.close();
}
其他位置都不需要修改,只需要修改resultMap中的配置:association即可。
第三种方式:两条SQL语句,分步查询。(这种方式常用:优点一是可复用,二是支持懒加载)
其他位置不需要修改,只需要修改以及添加以下三处:
第一处:association
中select
位置填写sqlId
。sqlId=namespace+id
。其中column
属性作为这条子sql语句的条件。
/*
* 分布查询第一步:先根据学生的sid查询学生的信息
* @param sid
* @version 1.0
*/
Student selectByIdStep1(Integer sid);
<resultMap id="studentReultMapByStep" type="Student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<association property="clazz"
select="com.powernode.mybatis.mapper.ClazzMapper.selectByIdStep2"
column="cid"/>
resultMap>
<select id="selectByIdStep1" resultMap="studentReultMapByStep">
select sid,sname,cid from t_stu where sid =#{sid}
select>
第二处:在ClazzMapper接口中添加方法
package com.powernode.mybatis.mapper;
import com.powernode.mybatis.pojo.Clazz;
public interface ClazzMapper {
/*
* 分别查询第二步:根据cid获取班级信息
* @param cid
* @version 1.0
*/
Clazz selectByIdStep2(Integer cid);
}
第三处:在ClazzMapper.xml文件中进行配置
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.powernode.mybatis.mapper.ClazzMapper">
<select id="selectByIdStep2" resultType="Clazz">
select cid,cname from t_clazz where cid = #{cid}
select>
mapper>
@Test
public void testSelectByIdStep1(){
SqlSession sqlSession = SqlSessionUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = mapper.selectByIdStep1(5);
System.out.println(student);
sqlSession.commit();
sqlSession.close();
}
什么是延迟加载(懒加载),有什么用?
延迟加载的核心原理是:用的时候再执行查询语句,不用的时候不查询
分步优点:
association
标签中添加fetchType="lazy"
fetchType="lazy"
association
标签中配置fetchType="lazy"
,是局部的设置,只对当前的association
关联的sql语句起作用。fetchType="eager"
来关闭懒加载lazyLoadingEnabled
属性,设置为true①:
<resultMap id="studentReultMapByStep" type="Student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
<association property="clazz"
select="com.powernode.mybatis.mapper.ClazzMapper.selectByIdStep2"
column="cid"
fetchType="lazy"/>
resultMap>
②:
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
settings>
在实际的开发中,大部分都是需要使用加载的,所以建议开启全部的延迟加载机制:
- 在mybatis核心配置文件中添加全局配置:
lazyLoadingEnabled=true
在实际开发中,开启全局的延迟加载机制,对于特殊不需要使用懒加载的通过
fetchType="eager
"来关闭懒加载
一对多的实现,通常是在一的一方中有List集合属性。
在Clazz类中添加List
属性。
public class Clazz {
private Integer cid;
private String cname;
private List<Student> stus;
// set get方法
// 构造方法
// toString方法
}
一对多的实现通常包括两种实现方式:
/**
* 根据cid获取Clazz信息
* @param cid
* @return
*/
Clazz selectByCollection(Integer cid);
package com.powernode.mybatis.pojo;
import java.util.List;
public class Clazz {
private Integer cid;
private String cname;
private List<Student> stus;
@Override
public String toString() {
return "Clazz{" +
"cid=" + cid +
", cname='" + cname + '\'' +
", stus=" + stus +
'}';
}
public List<Student> getStus() {
return stus;
}
public void setStus(List<Student> stus) {
this.stus = stus;
}
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public Clazz(Integer cid, String cname) {
this.cid = cid;
this.cname = cname;
}
public Clazz() {
}
}
<resultMap id="clazzResultMap" type="Clazz">
<id property="cid" column="cid"/>
<result property="cname" column="cname"/>
<collection property="stus" ofType="Student">
<id property="sid" column="sid"/>
<result property="sname" column="sname"/>
collection>
resultMap>
<select id="selectByCollection" resultMap="clazzResultMap">
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>
注意是ofType,表示“集合中的类型”。
package com.powernode.mybatis.test;
import com.powernode.mybatis.mapper.ClazzMapper;
import com.powernode.mybatis.pojo.Clazz;
import com.powernode.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
public class ClazzMapperTest {
@Test
public void testSelectByCollection(){
SqlSession sqlSession = SqlSessionUtil.openSession();
ClazzMapper mapper = sqlSession.getMapper(ClazzMapper.class);
Clazz clazz = mapper.selectByCollection(1000);
System.out.println(clazz);
sqlSession.commit();
sqlSession.close();
}
}
修改以下位置即可:
/*
* 分布查询:第一步,根据班级编号获取班级信息
* @param cid 班级编号
* @version 1.0
*/
Clazz selectByStep1(Integer cid);
/*
* 根据班级编号查询学生信息
* @param cid
* @version 1.0
*/
List<Student> selectByCidStep2(Integer cid);
<resultMap id="clazzResultMapStep" type="Clazz">
<id property="cid" column="cid"/>
<result property="cname" column="cname"/>
<collection property="stus"
select="com.powernode.mybatis.mapper.StudentMapper.selectByCidStep2"
column="cid"/>
resultMap>
<select id="selectByStep1" resultMap="clazzResultMapStep">
select cid,cname from t_clazz where cid = #{cid}
select>
<select id="selectByCidStep2" resultType="Student">
select * from t_stu where cid = #{cid}
select>
@Test
public void testSelectByStep1(){
SqlSession sqlSession = SqlSessionUtil.openSession();
ClazzMapper mapper = sqlSession.getMapper(ClazzMapper.class);
Clazz clazz = mapper.selectByStep1(1000);
System.out.println(clazz);
//只访问班级名字
System.out.println(clazz.getCname());
//只有用到的时候才会去执行第二步sql
System.out.println(clazz.getStus());
sqlSession.commit();
sqlSession.close();
}
fetchType=“lazy”
lazyLoadingEnabled=true
,如果开启全局延迟加载,想让某个sql不使用延迟加载:fetchType=“eager”
缓存:cache
缓存的作用:通过减少IO的方式,来提高程序的执行效率。
mybatis的缓存:将select语句的查询结果放到缓存(内存)当中,下一次还是这条select语句的话,直接从缓存中取,不再查数据库。一方面是减少了IO。另一方面不再执行繁琐的查找算法。效率大大提升。
常见的缓存技术:
mybatis缓存包括:
- 一级缓存:将查询到的数据存储到SqlSession中。
- 二级缓存:将查询到的数据存储到SqlSessionFactory中。
- 或者集成其它第三方的缓存:比如EhCache【Java语言开发的】、Memcache【C语言开发的】等。
缓存只针对于DQL语句,也就是说缓存机制只对应select语句。
一级缓存是默认开启的,不需要做任何配置。
原理:只要使用一个SqlSession对象执行一条SQL语句,就会走缓存
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.powernode.mybatis.mapper.CarMapper">
<select id="selectById" resultType="Car">
select * from t_car where id = #{id}
select>
mapper>
package com.powernode.mybatis.mapper;
import com.powernode.mybatis.pojo.Car;
public interface CarMapper {
Car selectById(Long id);
}
package com.powernode.mybatis.test;
import com.powernode.mybatis.mapper.CarMapper;
import com.powernode.mybatis.pojo.Car;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
public class CarMapperTest {
@Test
public void testSelectById() throws IOException {
//如果要获取不同的SqlSession对象,不能使用以下代码
// SqlSession sqlSession = SqlSessionUtil.openSession();
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);
Car car1 = mapper1.selectById(34L);
System.out.println(car1);
CarMapper mapper2 = sqlSession2.getMapper(CarMapper.class);
Car car2 = mapper2.selectById(34L);
System.out.println(car2);
//调用不同的sqlSession,缓存不一样
sqlSession1.commit();
sqlSession2.commit();
sqlSession1.close();
sqlSession2.close();
}
// @Test
// public void testSelectById(){
// SqlSession sqlSession = SqlSessionUtil.openSession();
// CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);
// Car car1 = mapper1.selectById(34L);
// System.out.println(car1);
//
// CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);
// Car car2 = mapper2.selectById(34L);
// System.out.println(car2);
// //可见都是基于sqlSession的,所以只会调用一个sql语句
// //一样的话就直接从缓存中调用出来
//
// sqlSession.commit();
// sqlSession.close();
// }
}
什么情况下不走缓存?
- 第一种:不同的SqlSession对象。
- 第二种:查询条件变化了。
一级缓存失效情况包括两种:
@Test
public void testSelectById(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);
Car car1 = mapper1.selectById(34L);
System.out.println(car1);
//手动清空了一级缓存
sqlSession.clearCache();
CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);
Car car2 = mapper2.selectById(34L);
System.out.println(car2);
sqlSession.commit();
sqlSession.close();
}
insert
delete
update
操作,一级缓存就失效。】 <insert id="insertClazz">
insert into t_clazz values (#{cid},#{cname});
insert>
/*
* 保存班级信息
* @param cid
* @param cname
* @version 1.0
*/
int insertClazz(@Param("cid") Integer cid, @Param("cname") String cname);
@Test
public void testSelectById(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper1 = sqlSession.getMapper(CarMapper.class);
Car car1 = mapper1.selectById(34L);
System.out.println(car1);
//手动清空了一级缓存
// sqlSession.clearCache();
//这里执行了insert delete update中的任意一个语句,并且和表没有关系
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
mapper.insertClazz(2000,"高三三班");
CarMapper mapper2 = sqlSession.getMapper(CarMapper.class);
Car car2 = mapper2.selectById(34L);
System.out.println(car2);
sqlSession.commit();
sqlSession.close();
}
二级缓存的范围是SqlSessionFactory。
使用二级缓存需要具备以下几个条件:
全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。默认就是true,无需设置。
在需要使用二级缓存的SqlMapper.xml文件中添加配置:
SqlSession
对象关闭或提交之后,一级缓存中的数据才会被写入到二级缓存当中。此时二级缓存才可用。
测试二级缓存:
<cache/>
public class Car implements Serializable {
//......
}
@Test
public void testSelectById2() throws IOException {
//这里只有一个SqlSessionFactory对象,二级缓存对应的就是SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);
CarMapper mapper2 = sqlSession2.getMapper(CarMapper.class);
//这行代码执行结束之后,实际上数据是缓存到一级缓存当中了(sqlSession是一级缓存)
Car car1 = mapper1.selectById2(34L);
System.out.println(car1);
//如果这里不关闭SqlSession对象的话,二级缓存中还是没有数据的
//如果执行了这行代码,sqlSession1的一级缓存中的数据会放到二级缓存当中
sqlSession1.close();
//这行代码执行结束之后,实际上数据会缓存到一级缓存当中(sqlSession是二级缓存)
Car car2 = mapper2.selectById2(34L);
System.out.println(car2);
//程序执行到这里的时候,会奖sqlSession1这个一级缓存中的数据写入到二级缓存当中
// sqlSession1.close();
//程序执行到这里的时候,会奖sqlSession2这个一级缓存中的数据写入到二级缓存当中
sqlSession2.close();
}
二级缓存的失效:只要两次查询之间出现了增删改操作。二级缓存就会失效。【一级缓存也会失效】
集成EhCache是为了代替mybatis自带的二级缓存。一级缓存是无法替代的。
mybatis对外提供了接口,也可以集成第三方的缓存组件。比如EhCache、Memcache等。都可以。
EhCache是Java写的。Memcache是C语言写的。所以mybatis集成EhCache较为常见,按照以下步骤操作,就可以完成集成:
<dependency>
<groupId>org.mybatis.cachesgroupId>
<artifactId>mybatis-ehcacheartifactId>
<version>1.2.2version>
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"/>
<defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"
timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>
ehcache>
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
@Test
public void testSelectById2() throws IOException {
//这里只有一个SqlSessionFactory对象,二级缓存对应的就是SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);
CarMapper mapper2 = sqlSession2.getMapper(CarMapper.class);
//这行代码执行结束之后,实际上数据是缓存到一级缓存当中了(sqlSession是一级缓存)
Car car1 = mapper1.selectById2(34L);
System.out.println(car1);
//如果这里不关闭SqlSession对象的话,二级缓存中还是没有数据的
//如果执行了这行代码,sqlSession1的一级缓存中的数据会放到二级缓存当中
sqlSession1.close();
//这行代码执行结束之后,实际上数据会缓存到一级缓存当中(sqlSession是二级缓存)
Car car2 = mapper2.selectById2(34L);
System.out.println(car2);
//程序执行到这里的时候,会奖sqlSession1这个一级缓存中的数据写入到二级缓存当中
// sqlSession1.close();
//程序执行到这里的时候,会奖sqlSession2这个一级缓存中的数据写入到二级缓存当中
sqlSession2.close();
}
日志信息又不一样了
所谓的逆向工程是:根据数据库表逆向生成Java的pojo类,SqlMapper.xml文件,以及Mapper接口类等。
要完成这个工作,需要借助别人写好的逆向工程插件。
思考:使用这个插件的话,需要给这个插件配置哪些信息?
- pojo类名、包名以及生成位置。
- SqlMapper.xml文件名以及生成位置。
- Mapper接口名以及生成位置。
- 连接数据库的信息。
- 指定哪些表参与逆向工程。…
第一步:基础环境准备
新建模块:模块名
打包方式:jar
第二步:在pom中添加逆向工程插件
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-maven-pluginartifactId>
<version>1.3.7version>
<configuration>
<overwrite>trueoverwrite>
configuration>
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.30version>
dependency>
dependencies>
plugin>
plugins>
build>
第三步:配置generatorConfig.xml
该文件名必须叫做: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="MyBatis3Simple">
<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>
第四步:在Mavn那里双击运行插件
但是注意,其他的什么源文件,比如:日志文件、核心配置文件、jdbc文件还是要自己弄
注意:自动生成的pojo类没有toString方法,要自己补上才能看到显示的
package com.powernode.mybatis.test;
import com.powernode.mybatis.mapper.CarMapper;
import com.powernode.mybatis.pojo.Car;
import com.powernode.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class CarMapperTest {
@Test
public void testSelectAll(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.selectAll();
cars.forEach(car -> System.out.println(car));
sqlSession.commit();
sqlSession.close();
}
}
前面的步骤同基础版一样
第三步:改变的增强版
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>
package com.powernode.mybatis.test;
import com.powernode.mybatis.mapper.CarMapper;
import com.powernode.mybatis.pojo.Car;
import com.powernode.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class CarMapperTest {
//CarExample类负责封装查询条件的
@Test
public void testSelect(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
//执行查询
//1.查询一个
Car car = mapper.selectByPrimaryKey(34L);
System.out.println(car);
//2.查询所有,如果条件是null,则表示没有条件
List<Car> cars = mapper.selectByExample(null);
cars.forEach(car1-> System.out.println(car1));
//3.按照条件进行查询
sqlSession.commit();
sqlSession.close();
}
}
package com.powernode.mybatis.test;
import com.powernode.mybatis.mapper.CarMapper;
import com.powernode.mybatis.pojo.Car;
import com.powernode.mybatis.pojo.CarExample;
import com.powernode.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.math.BigDecimal;
import java.util.List;
public class CarMapperTest {
//CarExample类负责封装查询条件的
@Test
public void testSelect(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
//执行查询
//1.查询一个
Car car = mapper.selectByPrimaryKey(34L);
System.out.println(car);
//2.查询所有,如果条件是null,则表示没有条件
List<Car> cars = mapper.selectByExample(null);
cars.forEach(car1-> System.out.println(car1));
System.out.println("==========================================");
//3.按照条件进行查询
//QBC 风格:Query By Criteria 一种查询方式:比较面向对象,看不到sql语句
// 封装条件,通过CarExample对象来封装查询条件
CarExample carExample = new CarExample();
//调用carExample.createCriteria()方法来创建查询条件
carExample.createCriteria()
.andBrandLike("byd")
.andGuidePriceGreaterThan(new BigDecimal(5.0));
//添加or
carExample.or().andCarTypeEqualTo("电车");
//执行查询
List<Car> cars2 = mapper.selectByExample(carExample);
cars2.forEach(car2-> System.out.println(car2));
sqlSession.commit();
sqlSession.close();
}
}
QBC 风格:Query By Criteria 一种查询方式,比较面向对象,看不到sql语句。
mysql的limit后面两个数字:
startIndex
(起始下标。下标从0开始。)pageSize
(每页显示的记录条数)假设已知页码pageNum,还有每页显示的记录条数pageSize,第一个数字可以动态的获取吗?
startIndex = (pageNum - 1) * pageSize
select
*
from
tableName ......
limit
(pageNum - 1) * pageSize, pageSize
使用mybatis应该怎么做?
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.powernode.mybatis.mapper.CarMapper">
<select id="selectByPage" resultType="Car">
select * from t_car limit #{startIndex},#{pageSize}
select>
mapper>
package com.powernode.mybatis.mapper;
import com.powernode.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface CarMapper {
/*
* @分页查询
* @param startIndex 起始下标
* @param pageSize 每页显示的记录条数
* @version 1.0
*/
List<Car> selectByPage(@Param("startIndex") int startIndex,@Param("pageSize") int pageSize);
}
package com.powernode.mybatis.test;
import com.powernode.mybatis.mapper.CarMapper;
import com.powernode.mybatis.pojo.Car;
import com.powernode.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class CarMapperTest {
@Test
public void testSelectByPage(){
// 获取每页显示的记录条数
int pageSize = 3;
//显示第几页:页码
int pageNum = 2;
// 计算开始下标
int startIndex = (pageSize - 1) *pageNum;
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.selectByPage(startIndex, pageSize);
cars.forEach(car -> System.out.println(car));
sqlSession.commit();
sqlSession.close();
}
}
获取数据不难,难的是获取分页相关的数据比较难。可以借助mybatis的PageHelper插件。
使用PageHelper插件进行分页,更加的便捷。
第一步:在pom文件里引入依赖
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>5.3.1version>
dependency>
第二步:在mybatis-config.xml文件中配置插件
typeAliases标签下面进行配置:
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">plugin>
plugins>
第三步:编写Java代码
<select id="selectAll" resultType="Car">
select * from t_car
select>
/*
* 查询所有car,通过分页查询插件PageHelper完成
* @version 1.0
*/
List<Car> selectAll();
@Test
public void testSelectAll(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
//一定一定耀注意:在执行DQL语句之前。开启分页功能
int pageNum = 2;
int pageSize = 3;
PageHelper.startPage(pageNum,pageSize);
List<Car> cars = mapper.selectAll();
cars.forEach(car -> System.out.println(car));
sqlSession.commit();
sqlSession.close();
}
关键点:
- 在查询语句之前开启分页功能。
- 在查询语句之后封装PageInfo对象。(PageInfo对象将来会存储到request域当中。在页面上展示。)
@Test
public void testSelectAll(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
//一定一定耀注意:在执行DQL语句之前。开启分页功能
int pageNum = 2;
int pageSize = 3;
PageHelper.startPage(pageNum,pageSize);
List<Car> cars = mapper.selectAll();
// cars.forEach(car -> System.out.println(car));
//封装分页信息对象new PageInfo()
// PageInfo对象是PageHelper插件提供的,用来封装分页相关的信息对象
PageInfo<Car> carPageInfo = new PageInfo<>(cars, 3);
System.out.println(carPageInfo);
sqlSession.commit();
sqlSession.close();
}
执行结果:
PageInfo{pageNum=2, pageSize=3, size=3, startRow=4, endRow=6, total=8, pages=3,
list=Page{count=true, pageNum=2, pageSize=3, startRow=3, endRow=6, total=8, pages=3, reasonable=false, pageSizeZero=false}[Car{id=4, carNum='9999', brand='magua', guidePrice=30, produceTime='1999-11-10', carType='旧能源'},
Car{id=6, carNum='8888', brand='法克鱿', guidePrice=30, produceTime='2000-11-66', carType='捞车'},
Car{id=7, carNum='8888', brand='法克鱿', guidePrice=30, produceTime='2000-11-66', carType='捞车'}],
prePage=1, nextPage=3, isFirstPage=false, isLastPage=false, hasPreviousPage=true, hasNextPage=true, navigatePages=3, navigateFirstPage=1, navigateLastPage=3, navigatepageNums=[1, 2, 3]}
pageNum页码
pageSize每页显示几条记录
startRow是整个mysql数据库表中从第几条记录开始
endRow是最后一条记录
total总记录条数
pages记录条数三页
mybatis中也提供了注解式开发方式,采用注解可以减少Sql映射文件的配置。
当然,使用注解式开发的话,sql语句是写在java程序中的,这种方式也会给sql语句的维护带来成本。
官方是这么说的:
使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL
语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。
原则:简单sql可以注解。复杂sql使用xml。
package com.powernode.mybatis.mapper;
import com.powernode.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Insert;
public interface CarMapper {
@Insert(value="insert into t_car values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})")
int insert(Car car);
}
package com.powernode.mybatis.test;
import com.powernode.mybatis.mapper.CarMapper;
import com.powernode.mybatis.pojo.Car;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
public class AnnotationTest {
@Test
public void testInsert() throws Exception{
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Car car = new Car(null, "1112", "卡罗拉", 30.0, "2000-10-10", "燃油车");
int count = mapper.insert(car);
System.out.println("插入了几条记录:" + count);
sqlSession.commit();
sqlSession.close();
}
}
@Delete("delete from t_car where id = #{id}")
int deleteById(Long id);
@Test
public void testDelete() throws Exception{
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
mapper.deleteById(89L);
sqlSession.commit();
sqlSession.close();
}
@Update("update t_car set car_num=#{carNum},brand=#{brand},guide_price=#{guidePrice},produce_time=#{produceTime},car_type=#{carType} where id=#{id}")
int update(Car car);
@Test
public void testUpdate() throws Exception{
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Car car = new Car(88L,"1001", "凯美瑞", 30.0,"2000-11-11", "新能源");
mapper.update(car);
sqlSession.commit();
sqlSession.close();
}
@Select("select * from t_car where id = #{id}")
})
Car selectById(Long id);
@Test
public void testSelectById() throws Exception{
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession = sqlSessionFactory.openSession();
CarMapper carMapper = sqlSession.getMapper(CarMapper.class);
Car car = carMapper.selectById(88L);
System.out.println(car);
}
@Select("select * from t_car where id = #{id}")
@Results({
@Result(column = "id", property = "id", id = true),
@Result(column = "car_num", property = "carNum"),
@Result(column = "brand", property = "brand"),
@Result(column = "guide_price", property = "guidePrice"),
@Result(column = "produce_time", property = "produceTime"),
@Result(column = "car_type", property = "carType")
})
Car selectById(Long id);