Mybatis(五) Mybatis是一款优秀的持久层框架,用于简化JDBC的开发。
入门程序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 //mapper包下 package com.ljsblog.mapper; import com.ljsblog.pojo.User; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import java.util.List; @Mapper public interface UserMapper { @Select("select * from user") public List<User> userList(); } //pojo包下 package com.ljsblog.pojo; public class User { private Integer id; private String name; private short age; private short gender; private String phone; public User() { } public User(Integer id, String name, short age, short gender, String phone) { this.id = id; this.name = name; this.age = age; this.gender = gender; this.phone = phone; } /** * 获取 * @return id */ public Integer getId() { return id; } /** * 设置 * @param id */ public void setId(Integer id) { this.id = id; } /** * 获取 * @return name */ public String getName() { return name; } /** * 设置 * @param name */ public void setName(String name) { this.name = name; } /** * 获取 * @return age */ public short getAge() { return age; } /** * 设置 * @param age */ public void setAge(short age) { this.age = age; } /** * 获取 * @return gender */ public short getGender() { return gender; } /** * 设置 * @param gender */ public void setGender(short gender) { this.gender = gender; } /** * 获取 * @return phone */ public String getPhone() { return phone; } /** * 设置 * @param phone */ public void setPhone(String phone) { this.phone = phone; } public String toString() { return "User{id = " + id + ", name = " + name + ", age = " + age + ", gender = " + gender + ", phone = " + phone + "}"; } } //application.properties spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/mybatis spring.datasource.username=root spring.datasource.password=root package com.ljsblog; //Test/java/com.ljsblog import com.ljsblog.mapper.UserMapper; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class SpringbootmybatisApplicationTests { @Autowired private UserMapper userMapper; @Test public void userList(){ userMapper.userList().stream().forEach(s-> System.out.println(s)); } }
JDBC JDBC :Java DataBase Connectivity,就是使用java语言操作关系型数据库的一套API。
sun公司官方定义一套操作所有关系型数据库的规范,即接口,各个数据库厂商(Mysql,Oracle等)去实现该接口,提供数据库驱动jar包,我们可用该接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。
数据库连接池 数据库连接池 是个容器,负责分配,管理数据库连接(Connection)
它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。
释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏。
优势 :
现常用数据库连接池产品
Druid
Hikari(Springboot默认)
若使用Druid需引入依赖
1 2 3 4 5 <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.8</version> </dependency>
lombok工具包 Lombok是一个实用的java类库,能通过注解的形式自动生成构造器,getter/setter,equals,hashcode,toString等方法,并可以自动化生成日志变量,简化Java开发,提高效率。
需引入依赖 :
1 2 3 4 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
注解 :
@Getter/@Setter
@ToString
@EqualsAndHashCode
根据类所拥有的非静态字段自动重写equals方法和hashCode方法
@Data
提供更综合的生成代码功能,相当于@Getter+@Setter+@ToString+@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
为实体类生成除了static修饰的字段之外带有各个参数的构造器方法
例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.ljsblog.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class User { private Integer id; private String name; private short age; private short gender; private String phone; }
Mybatis基础操作 参数占位符
#{…}
执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值
使用时机:参数传递,都使用#{…}
${…}
拼接SQL,直接将参数拼接在SQL语句中,存在SQL注入问题
使用时机:若对表名,列表进行动态设置时使用
删除 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 //Mapper package com.ljsblog.mapper; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Mapper; @Mapper public interface EmpMapper { @Delete("delete from emp where id=#{id}") public void delete(Integer id); } //Test @Test public void delete(){ empMapper.delete(17); }
注 :若mapper接口方法形参只有一个普通类型的参数,#{…}里面的属性名可以随便写。
日志输出 :
可在application.properties中,打开mybatis的日志,并指定输出到控制台。
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
添加(新增) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time) " +"values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},{updateTime})") public void insert(Emp emp); @Test public void insert(){ Emp emp=new Emp(); emp.setUsername("Jerry"); emp.setName("杰瑞"); emp.setGender((short)1); emp.setImage("1.jpg"); emp.setJob((short)1); emp.setEntrydate(LocalDate.of(2000,1,1)); emp.setCreateTime(LocalDateTime.now()); emp.setUpdateTime(LocalDateTime.now()); emp.setDeptId(1); empMapper.insert(emp); }
主键返回 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Options(useGeneratedKeys = true,keyProperty = "id")//获取返回的主键,并将其存入emp的id变量中 @Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time) " + "values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})") public void insert(Emp emp); @Test public void insert(){ Emp emp=new Emp(); emp.setUsername("Tom"); emp.setName("汤姆"); emp.setGender((short)1); emp.setImage("1.jpg"); emp.setJob((short)1); emp.setEntrydate(LocalDate.of(2000,1,1)); emp.setCreateTime(LocalDateTime.now()); emp.setUpdateTime(LocalDateTime.now()); emp.setDeptId(1); empMapper.insert(emp); System.out.println(emp.getId()); }
更新 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Update("update emp set username=#{username},name=#{name},gender=#{gender},image=#{image},job=#{job},entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime} where id=#{id}") public void update(Emp emp); @Test public void update(){ Emp emp=new Emp(); emp.setId(21); emp.setUsername("Tom1"); emp.setName("汤姆1"); emp.setGender((short)2); emp.setImage("2.jpg"); emp.setJob((short)2); emp.setEntrydate(LocalDate.of(2001,1,1)); emp.setUpdateTime(LocalDateTime.now()); emp.setDeptId(2); empMapper.update(emp); }
查询 根据id查询 数据封装 :
实体类属性名和数据库表查询返回的字段名一致,mybatis会自动封装
若实体类属性名和数据库表查询返回的字段名不一致,不能自动封装
开启驼峰命名 :若字段名与属性名符合驼峰命名规则,mybatis会自动通过驼峰命名规则映射,例如dept_id会变成deptId。
开启驼峰命名需在application.properties文件里加入以下代码:
mybatis.configuration.map-underscore-to-camel-case=true。
1 2 3 4 5 6 7 8 9 @Select("select * from emp where id=#{id}") public Emp select(int id); @Test public void select(){ System.out.println(empMapper.select(21)); } mybatis.configuration.map-underscore-to-camel-case=true。
条件查询 1 2 3 4 5 6 7 8 //sql,concat,拼接字符串 @Select("select * from emp where name like concat('%',#{name},'%') and gender=#{gender} and entrydate between #{begin} and #{end} order by update_time desc") public List<Emp> select1(String name, Short gender, LocalDate begin, LocalDate end); @Test public void select1(){ System.out.println(empMapper.select1("张",(short)1,LocalDate.of(2010,1,1),LocalDate.of(2020,1,1))); }
XML映射文件 规范
XML映射文件的名称和Mapper接口名称一致,并且将XML映射文件和Mapper放在相同名称的包下(同包同名)。
XML映射文件的namespace属性与Mapper接口全限定名一致
XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型的一致。
范例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public List<Emp> select2(String name, Short gender, LocalDate begin, LocalDate end); <?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"> <!--以上为固定,从https://mybatis.net.cn/getting-started.html复制--> <mapper namespace="com.ljsblog.mapper.EmpMapper"> <!-- resultType指单条记录所封装的类型--> <select id="select2" resultType="com.ljsblog.pojo.Emp"> select * from emp where name like concat('%',#{name},'%') and gender=#{gender} and entrydate between #{begin} and #{end} order by update_time desc </select> </mapper>
注解方式和XML方式
若执行简单的增删改查功能,使用注解。
若执行复杂的SQL功能,使用XML。
Mybatis动态sql 随着用户的输入或外部条件的变化而变化的语句,称为动态sql 。
标签 :
1 2 3 4 5 6 7 8 9 10 11 <if>用于判断条件是否成立,使用test属性进行条件判断,若条件为true,则拼接SQL <where>where元素只会在子元素有内容的情况才能插入where子句,而且会自动去除子句开头的AND或OR <set>动地在行首插入set关键字,并会删掉额外的逗号,用在update语句中 <foreach>遍历,属性: collection:集合名称 item:结合遍历出来的元素/项 separator:每次遍历使用的分隔符 open:遍历开始前拼接的片段 close:遍历结束后拼接的片段 <sql>定义可重用的SQL片段,属性值id <include>通过属性refid,指定包含的sql片段
范例1 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public List<Emp> select2(String name, Short gender, LocalDate begin, LocalDate end); <?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"> <!--以上为固定,从https://mybatis.net.cn/getting-started.html复制--> <mapper namespace="com.ljsblog.mapper.EmpMapper"> <!--resultType指单条记录所封装的类型--> <select id="select2" resultType="com.ljsblog.pojo.Emp"> select * from emp <where> <if test="name!=null"> name like concat('%', #{name}, '%') </if> <if test="gender!=null"> and gender = #{gender} </if> <if test="begin!=null and end!=null"> and entrydate between #{begin} and #{end} </if> </where> order by update_time desc </select> </mapper> @Test public void select2(){ System.out.println(empMapper.select2("张",null,null,null)); }
范例2 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public void update1(Emp emp); <update id="update1"> update emp <set> <if test="username!=null"> username=#{username}, </if> <if test="name!=null"> name=#{name}, </if> <if test="gender!=null"> gender=#{gender}, </if> <if test="image!=null"> image=#{image}, </if> <if test="job!=null"> job=#{job}, </if> <if test="entrydate!=null"> entrydate=#{entrydate}, </if> <if test="deptId!=null"> dept_id=#{deptId}, </if> <if test="updateTime!=null"> update_time=#{updateTime} </if> </set> where id = #{id} </update> @Test public void update1(){ Emp emp=new Emp(); emp.setId(21); emp.setUsername("Tom5"); emp.setName("汤姆5"); emp.setGender((short)3); emp.setDeptId(1); empMapper.update1(emp); }
范例3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public void delete1(List<Integer> ids); <delete id="delete1"> delete from emp where id in <foreach collection="ids" item="id" separator="," open="(" close=")"> #{id} </foreach> </delete> @Test public void delete1(){ List<Integer> ids= Arrays.asList(10,11); empMapper.delete1(ids); }
范例4:
1 2 3 4 5 6 7 8 9 10 11 12 public List<Emp> selectAll(); <sql id="all">select,id,username,password,name,gender,image,job,entrydate,dept_id,create_time,update_time</sql> <select id="selectAll" resultType="com.ljsblog.pojo.Emp"> <include refid="all"/> from emp </select> @Test public void allSelect(){ List<Emp> empList=empMapper.selectAll(); System.out.println(empList); }