本篇文章首先将教会大家如何搭建一个MyBatis,并使用MyBatis进行基本的增删改查操作
注意:本篇文章不过多的讲解原理
MyBatis环境搭建
依赖:
首先创建一个webapp文件,注意不要选择错误
我们需要在pom.xml中添加依赖
#注意使用jdk1.8及以上
#Lombok是Java语言的一个开源项目,它的目标是通过提供简单的注解和库函数,减少Java开发中冗余的样板代码。
在<dependencies> </dependencies>中添加
#lombok依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
#mybatis依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
#mysql依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
#添加完成后刷新一下
main:
在main下创建java和resources目录
创建实体类包,并根据自身数据库的一个表名创建一个实体类(类名不需要和表名一模一样)
com.ybg.MyBits.Entity.Activity
根据我们的表字段,写类属性,并导入lombok
设置实体类映射接口,编写实现方法接口
可以看到接口中的的方法名是操作+表名+By...这也是一种规范
对于参数,主要是看操作,例如插入操作我们需要给每一个字段插入数据,就传一个对象
删除操作,根据id去删除,那就给一个id类型的参数
对于查找可以没有参数,这些参数多在where子句中发挥作用,查找有返回值,返回一个对象
resources
接下来就是配置文件,这里比较重要建议能粘贴的一定要粘贴
首先创建数据库连接文件mybatis.cfg.xml
添加如下内容:
注意其中红颜色的地方是需要自己修改成相应的
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration> <environments default="主机名"> <environment id="主机名"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://IP地址:3306/数据库名?useUnicode=true&useSSL=false&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true&allowPublicKeyRetrieval=true"/> <property name="username" value="数据库用户名"/> <property name="password" value="数据库密码"/> </dataSource> </environment> </environments> </configuration>接下来配置实体类文件,因为表不只有一个,所以以后实体类也不只有一个,所以我们创建一个目录来存放实体类文件
#注意红色的地方
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ybg.mybatis.mapper.ActivityMapper"> <insert id="insertActivity" parameterType="com.ybg.mybatis.Entity.Activity"> insert into Activity values(#{player_id},#{device_id},#{event_date},#{games_played}) </insert> <delete id="deleteActivityByPID" parameterType="int"> delete from Activity where player_id=#{player_id} </delete> <update id="updateActivityByPID" parameterType="com.ybg.mybatis.Entity.Activity"> update Activity set device_id=#{device_id},event_date=#{event_date},games_played=#{games_played} where player_id=#{player_id} </update> </mapper>首先在mapper 里的namespace="..."里面放的是我们写的接口的路径
接下来就是一些操作我这里写了insert,delete,update操作,只写一个也行
属性id一定要和接口中的名一样,然后 参数类型parameterType 如果参数是一个类,那就存放类的路径,如果是int...就直接放int,对于String要放java.lang.String
#注意配置完成后,要在mybatis.cfg.xml中添加一些内容
测试:
创建Demo
在mydemo类中创建main
//加载配置文件(mybatis.cfg.xml) Reader read=Resources.getResourceAsReader("mybatis.cfg.xml"); //利用读取的文件生成工厂 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(read); //产生一次会话 SqlSession session = factory.openSession(); //利用会话获取数据库接口 ActivityMapper avm = session.getMapper(ActivityMapper.class);
注意不要导错包
#插入测试Activity av = Activity.builder().player_id(4).device_id(5).event_date(Date.valueOf("2017-06-08")).games_played(4).build(); try { avm.insertActivity(av); session.commit(); //一定要提交否则无效 System.out.println("成功插入数据"); } catch (Exception e) { session.rollback(); }这里创建对象就体现了lombok的方便,lombok使用一种语法以
类名.builder().属性......build()的格式,这样写几个属性就相当于几个属性的构造器
//删除测试 avm.deleteActivityByPID(4); session.commit(); //修改测试 Activity av = Activity.builder().player_id(2).device_id(7).event_date(Date.valueOf("2017-06-08")).games_played(4).build(); avm.updateActivityByPID(av); session.commit();
多表嵌套:resultMap的使用
这里的嵌套是指一个表是另一个表的属性 表→类
例如:
对于这两个类,Towercares中有一个iots属性,类型是InOutTime
这样就出现了一个问题,就是当我们查询Towercares时,由于表中没有iots列,所以这一列会默认为空,所以我们要把两个表关联起来,这里讲两种方法
1.foreach循环法
利用会话获得数据库接口
InOutTimeMapper iotm = session.getMapper(InOutTimeMapper.class); TowercaresMapper tcm = session.getMapper(TowercaresMapper.class); 将查询结果保存在集合中然后通过for向iots里set数据 List<Towercares> tower = tcm.findAll(); for(Towercares tc:tower){ List<InOutTime> iot = iotm.findInOutTimeByTcid(tc.getTcid()); tc.setIots(iot); } System.out.println(tower); 2.配置xml文件 我们可以先给两个表起别名,这样当需要到实体类的时候,就不再需要一长串了 再configuration中配置别名 然后,比如我们当前是需要查Towercares时同时把它的属性类型InOutTime表也查一下,那我们就去配置Towercares.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ybg.doubletest1.mapper.TowercaresMapper"> <resultMap id="tower-inouttime" type="tower"> <collection property="iots" column="tcid" select="com.ybg.doubletest1.mapper.InOutTimeMapper.findInOutTimeByTcid"> </collection> </resultMap> <select id="findAll" resultMap="tower-inouttime"> select * from towercares </select> </mapper> resultMap的id属性是两个表的别名用-连接,不用别名就需要用两个表的路径连接,type是当前xml文件的类的别名。 connection中 property是属性列名,column是InOutTime的参数,select是具体的方法路径。 注意下面的select语句的属性由resultType换成resultMap 之后我们可以直接打印Towercares的查询结果
动态SQL:where
以InOutTime表为例
如果我们需要按照特定的条件查询,就要在xml文件中配置,但是如果我们对于整个表,想要用每个字段都来查一次我们就需要写5条select语句
select * from InOutTime where ioid=#{ioid}
select * from InOutTime where project=#{project}
......我们还可能按照2个、3个、4个来查,这样一旦字段很多是不可取的,所以出现了动态SQL
1.修改接口方法接口的参数由字段换成类
2.修改xml文件
<select id="findInOutTime" parameterType="inouttime" resultType="inouttime"> select * from inouttime <where> <if test="ioid!=0"> ioid=#{ioid} </if> <if test="project!=null"> and project=#{project} </if> <if test="tcid!=0"> and tcid=#{tcid} </if> <if test="intime!=null"> and intime=#{intime} </if> <if test="outtime"> and outtime=#{outtime} </if> </where> </select> 我们使用where if test 进行判断来进行拼接在counfiguration中添加
在输出时可以看到自己拼接的语句
在main中
InOutTimeMapper iotm = session.getMapper(InOutTimeMapper.class); InOutTime io1 = new InOutTime().builder().tcid(1).build(); System.out.println(iotm.findInOutTime(io1));
动态SQL:foreach
foreach动态SQL主要是为了我们有大量数据插入需求时使用的
正常我们插入两条语句
<insert id="insertOutTime" parameterType="iotime"> insert into inouttime values(#{ioid},#{project},#{tcid},#{intime},#{outtime}),(#{ioid},#{project},#{tcid},#{intime},#{outtime}) </insert> 如果我们插入几万条不可能写几万个然后用逗号分开 此时我们可以使用foreach 语法格式: interface中定义 public void batchInsertInOutTime(List<InOutTime> iots); xml文件中配置 <insert id="batchInsertInOutTime"> insert into inouttime values <foreach collection="list" item="io" separator=","> (#{io.ioid},#{io.project},#{io.tcid},#{io.intime},#{io.outtime}) </foreach> </insert> Demo中测试: 先将数据存放到List集合中 List<InOutTime> iotimes=new ArrayList<>(); for (int i = 5; i < 210001; i++) { InOutTime io = InOutTime.builder().ioid(i).tcid(i % 2 + 1).project("地铁1号线" + i + "工程").intime(Date.valueOf("2005-04-04")).outtime(Date.valueOf("2008-05-04")).build(); iotimes.add(io); } 通过方法插入到表中 for (int j =0; j <20; j++) { iom.batchInsertInOutTime(iotimes.subList(j*10000,j*10000+10000)); session.commit(); }
数据分页
依赖:
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.2.0</version> </dependency> 数据分页大致分为3步 1.设置页码和每页的行数 PageHelper.startPage(pageNum,pageSize) 2.获取数据存放到集合中 List<Towercares> tcs=tm.findAll(); 3.创建PageInfo对象 PageInfo<Towercares> pi =new PageInfo<>(tcs); 测试 System.out.println(pi);