一、Mybatis概述
1.Mybatis是一款优秀的持久层框架,用于简化JDBC开发。
2.持久层:负责将数据保存到数据库的那一层代码
二、Mybatis的重要配置文件mybatis-config.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:配置数据库连接环境信息。可以配置多个environment,通过default属性切换不同的environment
-->
<!--不用在sql映射文件中写resultMap-->
<!--mybatis开启驼峰命名法可以使表中的数据类型例如:brand_name变成brandName的形式,与java实体类中成员变量的命名方法相同,这样从数据库中查询到的值就可以被包装成对应的类-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--数据库连接信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<mappers>
<!--<mapper resource="UserMapper.xml"/>-->
<!--Mapper代理方式,用包扫描添加sql映射文件-->
<!--会自动扫描cn.mapper包下的xml配置文件-->
<package name="cn.mapper"/>
</mappers>
三、Mybatis代理模式中重要的三个文件
1.mybatis-config.xml、2.sql映射文件XxxMapper.xml、3.映射文件的接口类XxxMapper.java。sql映射文件的名字应该与接口类的名字形同,并在相同的路径下
1.1 mybatis-config.xml
需要配置数据库连接池的相关信息,以及关联sql映射文件。同上
1.2XxxMapper.xml文件
1.2.1统一管理sql语句,在代理模式下需要将sql映射文件放在与mapper接口类存放路径相同的路径中,如mapper接口在:cn.mapper路径下,则Xxx.xml文件也应该在放在cn.mapper路径下如图:
1.2.2设置SQL映射文件的namespace属性为Mapper接口的全类名
如图:
1.3XxxMapper.java文件
在Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持返回值类型一样
方法的实现:
BrandMapper.java:
package cn.mapper;
import cn.pojo.Brand;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface BrandMapper {
List<Brand> selectAll();
Brand selectById(int id);
// @Param给参数命名,使得mapper.xml文件中的sql语句可以使用成员变量当做参数
Brand selectByIdAndNameAndStatus(@Param("id") int id, @Param("brandName")String brandName, @Param("status")int status);
}
代码中多参数为什么用了@Param注解:
我们在接口方法中定义多个参数,Mybatis 会将这些参数封装成 Map 集合对象,值就是参数值,而键在没有使用 @Param
注解时有以下命名规则:
1.以 arg 开头 :第一个参数就叫 arg0,第二个参数就叫 arg1,以此类推。例如:
map.put("arg0",参数值1);
map.put("arg1",参数值2);
2.以 param 开头 : 第一个参数就叫 param1,第二个参数就叫 param2,依次类推。如:
map.put("param1",参数值1);
map.put("param2",参数值2);
在接口方法参数上使用 @Param
注解,Mybatis 会将 arg
开头的键名替换为对应注解的属性值。此处的@Param(“brandName”)就是为了对应BrandMapper.xml文件中select语句中的#{brandName}占位符,#{}:会替换为?,为了防止sql注入;${}:字符串的拼接,存在sql注入的风险
例如
Brand selectByIdAndNameAndStatus(@Param("id") int id, @Param("brandName")String brandName, @Param("status")int status);
注:此处学习时将mybatis开启驼峰命名发和@Param的使用混淆了。驼峰命名的开启是为了在从数据库中查询到数据时,数据库数据可以按照java实体类的成员变量命名方式给成员变量进行赋值,这样才可以封装成类,@param注解是为了接口中的方法传递多个参数时,可以用自定义的名字和sql映射文件中的占位符进行匹配。
BrandMapper.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就需要为BrandMapper.java的全类名-->
<mapper namespace="cn.mapper.BrandMapper">
<!--resultType将来数据包装成什么类型-->
<!--mybatis配置了别名,默认为实体类的名称,不区分大小写-->
<!--数据库中的字段名称和实体类中的成员变量名称不一样,则不能自动封装,可以使用<resultMap>标签进行映射-->
<!--之后用resultMap属性替换select标签中的resultType属性-->
<!-- <resultMap id="brandResultMap" type="cn.pojo.Brand">
<!–id:标签完成的是主键字段的映射–>
<!–resutl:标签完成的是一般字段的映射–>
<result column="brand_name" property="brandName"></result>
<result column="company_name" property="companyName"></result>
</resultMap>-->
<select id="selectAll" resultType="cn.pojo.Brand">
select * from tb_brand;
</select>
<!--parameterType可以省略不写-->
<!--处理特殊字符的方法
1.转义字符
2.CDATA区
-->
<select id="selectById" parameterType="integer" resultType="cn.pojo.Brand">
select * from tb_brand where id = #{id}
</select>
<!--如果在BrandMapper.java文件中没有使用@Param注解则#{id},#{brandName} ,#{status}是无法正确找到对应值的-->
<select id="selectByIdAndNameAndStatus" resultType="cn.pojo.Brand">
select * from tb_brand where id = #{id} and brand_name=#{brandName} and status = #{status}
</select>
</mapper>
Mybatis参数传递
多个参数:
上文已写
单个参数:单个参数又可以是如下类型
- POJO 类型
- Map 集合类型
- Collection 集合类型
- List 集合类型
- Array 类型
- 其他类型
具体实现:
POJO 类型: 直接使用。要求 属性名
和 参数占位符名称
一致。
Map 集合类型:直接使用。要求 map集合的键名
和 参数占位符名称
一致。
Collection 集合类型: Mybatis 会将集合封装到 map 集合中,如下:
map.put(“arg0”,collection集合);
map.put(“collection”,collection集合;
可以使用@Param
注解替换map集合中默认的 arg 键名。
List 集合类型:Mybatis 会将集合封装到 map 集合中,如下:
map.put(“arg0”,list集合);
map.put(“collection”,list集合);
map.put(“list”,list集合);
可以使用@Param
注解替换map集合中默认的 arg 键名。
Array 类型: Mybatis 会将集合封装到 map 集合中,如下:
map.put(“arg0”,数组);
map.put(“array”,数组);
可以使用@Param
注解替换map集合中默认的 arg 键名。
其他类型: 比如int类型,参数占位符名称
叫什么都可以。尽量做到见名知意
使用代理模式完成增删改查:
mybatis-config.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>
<!--开启驼峰命名法-->
<!--不用在sql映射文件中写resultMap-->
<!--数据库中的字段命名方式与pojo类中的成员变量命名方式不同,无法自动封装-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db5?useSSL=false&serverTimezone=GMT"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--<mapper resource="UserMapper.xml"/>-->
<!--Mapper代理方式,用包扫描添加sql映射文件-->
<package name="cn.mapper"/>
</mappers>
</configuration>
BrandMapper.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="cn.mapper.BrandMapper">
<!--无条件查询-->
<select id="selectAll" resultType="cn.pojo.Brand">
select * from tb_brand
</select>
<!--条件查询-->
<select id="selectByIdAndCompanyName" resultType="cn.pojo.Brand">
select * from tb_brand where id = #{id} and company_name = #{companyName}
</select>
<!--修改-->
<update id="updateBrandNameById">
update tb_brand set brand_name = #{brandName} where id = #{id}
</update>
<!--添加-->
<insert id="addBrand">
insert into tb_brand(id,brand_name,company_name,ordered,description ,status)
values(#{id},#{brandName},#{companyName},#{ordered},#{description},#{status})
</insert>
<!--删除-->
<delete id="deleteBrandById">
delete from tb_brand where id = #{id}
</delete>
</mapper>
BrandMapper.java接口类:
package cn.mapper;
import cn.pojo.Brand;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface BrandMapper {
List<Brand> selectAll();
List<Brand> selectByIdAndCompanyName(@Param("companyName") String companyName,@Param("id") int id);
int updateBrandNameById(@Param("brandName") String brandName,@Param("id") int id);
//传一个对象进去,mybatis会自己进行赋值
int addBrand(Brand brand);
int deleteBrandById(int id);
}
Brand类(实体类存放在pojo文件下或domain文件下):
package cn.pojo;
public class Brand {
private Integer id;
private String brandName;
private String companyName;
private Integer ordered;
private String description;
private Integer status;
public Brand() {
}
public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) {
this.id = id;
this.brandName = brandName;
this.companyName = companyName;
this.ordered = ordered;
this.description = description;
this.status = status;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getBrandName() {
return brandName;
}
public void setBrandName(String brandName) {
this.brandName = brandName;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public Integer getOrdered() {
return ordered;
}
public void setOrdered(Integer ordered) {
this.ordered = ordered;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
@Override
public String toString() {
return "Brand{" +
"id=" + id +
", brandName='" + brandName + '\'' +
", companyName='" + companyName + '\'' +
", ordered=" + ordered +
", description='" + description + '\'' +
", status=" + status +
'}';
}
}
测试类:
import cn.mapper.BrandMapper;
import cn.pojo.Brand;
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.InputStream;
import java.util.List;
public class Mybatis_CRID_Test {
@Test
public void selectTest() throws Exception{
// 加载mybatis的核心配置文件
// 也可用Brand.class.getClassLoader().getResourceAsStream();
String resource = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(resource);
// 解析配置文件(链接池,重要的map集合里面放置 键(sqlid)值(Mapper(sql,resultType))
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sessionFactory = builder.build(in);
// 开启sqlsession
SqlSession sqlSession = sessionFactory.openSession();
// 使用sqlSession的创建mapper接口队形执行对应方法
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
List<Brand> brands = mapper.selectAll();
for (Brand brand : brands) {
System.out.println(brand);
}
sqlSession.close();
}
@Test
public void selectTest2() throws Exception{
String resource = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sessionFactory = builder.build(in);
SqlSession sqlSession = sessionFactory.openSession();
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
List<Brand> brands = mapper.selectByIdAndCompanyName("华为技术有限公司",2);
for (Brand brand : brands) {
System.out.println(brand);
}
sqlSession.close();
}
@Test
public void InsertTest() throws Exception{
String resource = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sessionFactory = builder.build(in);
SqlSession sqlSession = sessionFactory.openSession();
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
Brand brand = new Brand(null,"阿迪达斯","阿迪达斯",5,"结实耐用,just do it",0);
int row = mapper.addBrand(brand);
if (row>0){
System.out.println("插入成功");
}else{
System.out.println("插入失败");
}
sqlSession.commit();
sqlSession.close();
}
@Test
public void updateTest() throws Exception{
String resource = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sessionFactory = builder.build(in);
SqlSession sqlSession = sessionFactory.openSession();
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
int row = mapper.updateBrandNameById("三叶草",5);
if (row>0){
System.out.println("修改成功");
}else{
System.out.println("修改失败");
}
sqlSession.commit();
sqlSession.close();
}
@Test
public void deleteTest() throws Exception{
String resource = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sessionFactory = builder.build(in);
SqlSession sqlSession = sessionFactory.openSession();
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
int row = mapper.deleteBrandById(5);
if (row>0){
System.out.println("删除成功");
}else{
System.out.println("删除失败");
}
sqlSession.commit();
sqlSession.close();
}
}
依赖
pom.xml
<groupId>org.example</groupId>
<artifactId>day05-mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.20</version>
</dependency>
</dependencies>