目录
3、编写Mybatis核心配置文件 mybatis-config.xml
4、编写SQL映射文件:SQL语句代码UserMapper.xml
一、Maven
1、Maven简介
pom 就是 project object moudle 项目对象模型
配置完pom.xml文件之后,相对应的jar包就会出现在项目中,不需要再手动导包,而实际在maven中有一个本地仓库,仓库中存放有相对应的jar包,它只是通过本地仓库将jar包导入项目。
由于中央仓库是由maven团队维护,由于仓库位置在国外,在国内访问速度较慢,所以一般公司会搭建自己的私服,将中央仓库的jar包同步下来,通过访问私服速度更快,中央仓库中存放的都是开源的jar包,带版权的jar只能在私服中
仓库工作流程:
项目1中需要某个jar包,向本地仓库申请,本地仓库中没有再向中央仓库中申请,并将相对应的jar包保存在本地仓库,然后导入项目1中,这时项目2需要用到该jar包时直接向本地仓库申请后导入。但如果架设了私服,本地仓库会先向私服请求,私服没有才会向中央仓库请求,然后将jar包下载到私服,再保存到本地仓库。
2、Maven的特点
2.1、Maven提供了一套标准化的的项目结构
2.2、提供了一套标准化构建流程
2.3、提供了一套依赖管理机制
maven通过核心配置文件直接导包,不需要再下载后右键导包。
3、安装Maven
在setting文件中指定本地仓库
<localRepository>D:\2ProgramTool\Intellij idea\apache\maven cangku</localRepository>
4、Maven常用命令
compile编译,将代码编译成 字节码文件,生成目标文件target文件
clean清理,将目标文件删除
test测试,执行test文件夹下的测试代码,输出测试结果
package打包,将该maven项目打包成jar文件
install安装,将该maven项目的jar包下载进本地仓库
使用Maven可以将项目打包!!
5、Maven生命周期
Maven对项目构建的生命周期分为3套 :clean、default、site
6、在IDEA中配置Maven
6.1、配置Maven环境
6.2、了解Maven坐标![](https://img-blog.csdnimg.cn/e624c27b546f4b4ca181fdcfbb63eae1.png)
6.3、创建Maven项目
6.4、导入Maven项目
7、依赖管理
7.1、导入依赖
<!--导入当前需要的依赖包-->
<!--dependencies 依赖,复数形式,多个依赖-->
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!--选择版本后会标红,说明本地仓库没有这个版本信息,点击右侧Maven标志,刷新就会自动下载-->
<version>5.1.34</version>
</dependency>
<dependency>
<!--设置IDEA,修改立即生效就不需要点击侧边Maven-->
<!--也可使使用快捷键Alt+Ins然后搜索,快速导入相关依赖-->
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
</dependencies>
7.2、依赖范围
运行环境不存在说明这个依赖不会存在打包好的jar包中。
二、MyBatis
1、Mybatis定义
与数据库进行操作的代码称为持久层。三层框架:表现层,业务层,持久层 -> 前端、后端、数据库
2、JDBC的缺点
3、Mybatis简化JDBC
将数据库连接和数据库操作都写在依赖中
4、Mybatis快速入门
-
1、创建user表,添加数据
CREATE DATABASE mybatis;
USE mybatis;
DROP TABLE IF EXISTS tb_user;
CREATE TABLE tb_user(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(10),
password VARCHAR(10),
gender CHAR(1),
addr VARCHAR(30)
);
INSERT INTO tb_user(username,password,gender,addr)
VALUES
('张三','12345','男','安徽'),
('李四','14335','男','芜湖'),
('王五','16745','女','南京');
-
2、创建Maven模块,导入坐标
-
3、编写Mybatis核心配置文件 mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--Mybatis核心配置文件-->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<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/mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="12345"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--加载SQL映射文件-->
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
-
4、编写SQL映射文件:SQL语句代码UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--SQL映射文件-->
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--mapper根标签 namespace必须要指定名称-->
<mapper namespace="test">
<!--id 表示SQL语句的唯一标识
resultType 表示SQL执行后返回结果的类型-->
<select id="selectAll" resultType="com.itheima.pojo.User">
select * from tb_user;
</select>
</mapper>
-
5、创建User类
public class User {
private Integer id;
private String username;
private String password;
private String gender;
private String addr;
-
6、编写主程序
public class MybatisDemo {
public static void main(String[] args) throws Exception {
//1、加载Mybatis核心配置文件,获取SqlSessionFactory
String resource = "mybatis-config.xml";
//Mybatis提供了资源加载类Resource,通过静态方法getResourceAsStream将字符串返回成一个字节输入流
InputStream inputStream = Resources.getResourceAsStream(resource);
//再通过SqlSessionFactoryBuilder对象的build方法获取字节输入流创建一个sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2、用sqlSessionFactory获取对应sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//3、执行sql
//传入SQL语句的唯一标识需要跟上名称空间
List<User> users = sqlSession.selectList("test.selectAll");
System.out.println(users);
//4、释放资源
sqlSession.close();
}
}
5、IDEA集成操作Navicat
点击右侧DataBase点击加号,创建一个数据库连接,再点击🖊进行SQL语法编写,代码会自动补全
6、使用Mapper代理方式完成入门案例
由于入门案例中的Mybatis简化后仍然存在硬编码问题,代码不灵活,所以使用Mapper代理方式进一步解决硬编码问题
-
1、定义同名的Mapper接口,并放置在同一目录下
右键单击resources新建文件,文件格式与Mapper接口的包名一致,中间用 / 做分隔符
文件创建成功后,将Mapper映射文件拖入文件夹中
编译Maven项目查看class文件,Mapper接口与映射文件在同一文件夹下
-
2、设置SQL映射文件的namespace为接口的全限定名
<!--mapper根标签 namespace必须要指定名称-->
包名.类名
<mapper namespace="com.itheima.mapper.UserMapper">
<!--id 表示SQL语句的唯一标识
resultType 表示SQL执行后返回结果的类型-->
<select id="selectAll" resultType="com.itheima.pojo.User">
select * from tb_user;
</select>
</mapper>
-
3、在Mapper接口中定义方法
public interface UserMapper {
//定义一个与SQL映射文件id同名的方法
//返回SQL映射文件中对应的返回值类型,还要根据SQL语义判断具体返回值类型
List<User> selectAll();
}
注意:由于Mapper映射文件位置已经更改,所以在Mybatis核心配置文件中修改映射文件的位置
<mappers>
<!--加载SQL映射文件-->
<mapper resource="com/itheima/mapper/UserMapper.xml"/>
</mappers>
-
4、编码
//3、执行sql
//获取UserMapper接口的代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.selectAll();
System.out.println(userList);
7、Mybatis核心配置文件详解
<?xml version="1.0" encoding="UTF-8" ?>
<!--Mybatis核心配置文件-->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--
使用typeAliases再进行包扫描,给该包下的所有实体类起别名,直接使用不区分大小写的类名
例如SQL映射文件下的返回值类型可以直接使用user,而不是com.itheima.pojo.user
-->
<typeAliases>
<package name="com.itheima.pojo"/>
</typeAliases>
<!--environments:配置数据库连接环境信息,可以配置多个environment,通过default属性切换不同的environment-->
<environments default="development">
<environment id="development">
<!--事物的管理方式-->
<transactionManager type="JDBC"/>
<!--数据库连接池,默认为POOLED-->
<dataSource type="POOLED">
<!--数据库连接信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="12345"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--加载SQL映射文件-->
<mapper resource="com/itheima/mapper/UserMapper.xml"/>
</mappers>
</configuration>
8、Mybatis实战案例(使用配置文件实现增删改查)
1、查询所有数据
发现问题:在查询数据并对数据进行输出时发现,从数据库中查找的数据不能很好的封装成User类存储的值是null。
由于数据库中列名为user_name,而User实体类中对应的用户名为userName,两者名称不同对应不上无法自动的封装数据。
三种修改方式:
<!--
数据库表的字段名称 和 实体类的属性名称不一样 ,则不能自动封装数据
*第一种方式:起别名 使两个名称相同 缺点:每次查询都要定义一次别名
*第二种方式 使用Sql片段 缺点:不灵活
*第三种方式 使用resultMap映射
-->
<!--<select id="selectAll" resultType="User">
<!--第一种起别名 缺点:每次查询都要定义一次别名-->
select
id, user_name as userName, password, gender, addr
from tb_user;
</select>
<sql id="user_column">
id, user_name as userName, password, gender, addr
</sql>
<select id="selectAll" resultType="User">
<!--第二种方式:sql片段, 缺点:对部分列名查询时要重写一个sql片段-->
select
<include refid="user_column"></include>
from tb_user;
</select>
<resultMap id="userResultMap" type="user">
<!--resultMap有两个常用属性 id:设置主键字段的映射 result:设置一般字段的映射-->
<!--column 表的列名 property 实体类的属性名-->
<result column="user_name" property="username"></result>
</resultMap>
<select id="selectAll" resultMap="userResultMap">
<!--第三种方式:使用resultMap映射,select标签中要记得修改为resultMap-->
select
*
from tb_user;
</select>
数据成功封装
2、查看商品详情
<!--
*参数占位符
1、#{}: 会将其替换成?,为了防止SQL注入
2、${}: 字符串拼接,直接将参数拼到字符串,会存在SQL注入问题
使用时机:*参数传递的时候:#{}
*表名或者列名不固定 ${}
3、特殊字符: xml文件中的一些比较运算符不能直接使用,要适应注意字符 <
-->
<select id="selectById" resultMap="userResultMap">
select *
from tb_user where id = #{id};
</select>
public interface UserMapper {
//1、查询所有
List<User> selectAll();
//2、查看详情,根据id查询
User selectById(int id);
3、多条件查询
多条件查询,传入多个参数有三种传参方式 :
方法一:散装参数
public interface UserMapper {
//1、查询所有
List<User> selectAll();
//2、查看详情,根据id查询
User selectById(int id);
//3、多条件查询
//三种方式的参数接收
//1、散装参数,存在多个参数使用@Param("占位符名称")注解
List<User> selectByFields(@Param("username") String username,@Param("gender") String gender,@Param("addr") String addr);
<select id="selectByFields" resultMap="userResultMap">
select
*
from tb_user
where
user_name = #{username}
and gender = #{gender}
and addr like #{addr};
</select>
//接收参数
String username = "张三";
String gender = "男";
String addr = "徽";
//处理参数 模糊查询
addr = "%" + addr;
//4、执行接口方法(执行SQL语句) 通过接口方法执行SQL语句
List<User> user = usermapper.selectByFields(username,gender,addr);
System.out.println(user);
方法二:传入对象参数
//接口
// 2、对象参数:传入一个对象,对象的属性名称要与参数占位符名称一致
List<User> selectByFields(User user);
//接收参数
String username = "张三";
String gender = "男";
String addr = "徽";
//处理参数
addr = "%" + addr;
//封装对象
User user = new User();
user.setUsername(username);
user.setGender(gender);
user.setAddr(addr);
//4、执行接口方法(执行SQL语句) 通过接口方法执行SQL语句
List<User> users = usermapper.selectByFields(user);
方法三:map集合做参数(HashMap)
//接口
//3、传入Map集合
List<User> selectByFields(Map map);
//接收参数
String username = "张三";
String gender = "男";
String addr = "徽";
//处理参数
addr = "%" + addr;
//添加Map集合
Map map = new HashMap();
//键:xml中的占位符名称,值:传入的参数
map.put("username",username);
map.put("gender",gender);
map.put("addr",addr);
//4、执行接口方法(执行SQL语句) 通过接口方法执行SQL语句
List<User> users = usermapper.selectByFields(map);
多条件查询当前存在的弊端:如果用户只输入其中一个数据就进行查询结果会查不到任何数据,所以需要采用动态查询方式
4、多条件动态查询
使用if实现动态查询
<select id="selectByFields" resultMap="userResultMap">
select
*
from tb_user
where
/*test中判断的值是传入的占位符的值,判断占位符是否为空字符串或者空字符,不能使用表名*/
/*多条件的and不能丢*/
<if test="username != null and username != ''">
user_name = #{username}
</if>
<if test="gender != null and gender != ''">
and gender = #{gender}
</if>
<if test="addr != null and addr != ''">
and addr like #{addr};
</if>
</select>
//接收参数
String username = "张三";
String gender = "男";
String addr = "徽";
//处理参数
addr = "%" + addr;
//添加Map集合
// 只输入两个数据
Map map = new HashMap();
//键:xml中的占位符名称,值:传入的参数
map.put("username",username);
map.put("gender",gender);
//map.put("addr",addr);
//4、执行接口方法(执行SQL语句) 通过接口方法执行SQL语句
List<User> users = usermapper.selectByFields(map);
当前问题:仅仅使用if语句会有bug,如果多条件查询中,用户没有输入第一个条件,而选择了后面的条件,此时第二条语句就会变成第一条语句使得SQL语句变成了
select * from tb_user where and gender=?
解决问题:在where后面加上恒等式1=1,并在每条语句前都加上and就可以解决问题
<select id="selectByFields" resultMap="userResultMap"> select * from tb_user where 1 = 1 /*test中判断的值是传入的占位符的值,判断占位符是否为空字符串或者空字符,不能使用表名*/ /*多条件的and不能丢*/ <if test="username != null and username != ''"> and user_name = #{username} </if> <if test="gender != null and gender != ''"> and gender = #{gender} </if> <if test="addr != null and addr != ''"> and addr like #{addr}; </if> </select>
也可以使用Mybatis提供的<where>标签来代替where语句,满足其中的条件就能执行
<select id="selectByFields" resultMap="userResultMap"> select * from tb_user <where> <!--test中判断的值是传入的占位符的值,判断占位符是否为空字符串或者空字符,不能使用表名--> <!--多条件的and不能丢--> <if test="username != null and username != ''"> and user_name = #{username} </if> <if test="gender != null and gender != ''"> and gender = #{gender} </if> <if test="addr != null and addr != ''"> and addr like #{addr}; </if> </where> </select>
5、单条件动态查询
使用choose实现单条件动态查询
choose就相当于switch when某个条件成立 执行代码 otherwise相当于default 恒等式
<select id="selectByFild" resultMap="userResultMap">
select
*
from tb_user
<!--where不能丢-->
where
<choose>
<when test="username != null and username != ''">
user_name = #{username}
</when>
<when test="gender != null and gender != ''">
gender = #{gender}
</when>
<when test="addr != null and addr != ''">
addr like #{addr}
</when>
<otherwise>
1 = 1
</otherwise>
</choose>
</select>
使用<where>标签代替where语句,可以省略1=1
<select id="selectByField" resultMap="userResultMap">
select
*
from tb_user
<where><!--满足其中的条件就能执行-->
<choose>
<when test="username != null and username != ''">
user_name = #{username}
</when>
<when test="gender != null and gender != ''">
gender = #{gender}
</when>
<when test="addr != null and addr != ''">
addr like #{addr}
</when>
</choose>
</where>
</select>
6、添加数据
直接添加数据
<insert id="add">
insert
into tb_user(user_name,password,gender,addr)
values
(#{username},#{password},#{gender},#{addr});
</insert>
//测试类
//接收参数
String username = "赵六";
String password = "123789";
String gender = "男";
String addr = "滁州";
User user = new User(username,password,gender,addr);
//4、执行接口方法(执行SQL语句) 通过接口方法执行SQL语句
usermapper.add(user);
发现问题:代码运行正常,但是数据库中却没有显示添加的数据
解决问题:执行完后需要手动提交事务
//提交事务 sqlSession.commit();
可以在建立SqlSession对象时设置自动提交事务
//1、加载mybatis核心配置文件获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2、获取SqlSession对象 //设置参数 true 自动提交事务,默认手动提交 SqlSession sqlSession = sqlSessionFactory.openSession(true);
使用此方式添加数据的缺点: 数据添加后无法通过封装的数据访问到数据库中的id值
添加数据--主键返回
只需要对SQL语句设置两个属性就能获取到对应的id值
在Mybatis中useGeneratedKeys属性只针对insert语句生效,默认为false,当设置为true时,表示插入的表以自增列为主键,则允许JDBC自动生成主键(对主键字段对应的实体类属性进行赋值)并可将此主键值返回,前提是主键必须自增。
keyProperty属性中必须填写的是主键字段对应的实体类属性名称,以确保实体类对象通过Mybatis增加到数据库之后得到的id增长值会被设置在实体类对应的属性值上。
public class User {
//实体类属性值
private Integer id;
private String username;
private String password;
private String gender;
private String addr;
<insert id="add" useGeneratedKeys="true" keyProperty="id">
insert
into tb_user(user_name,password,gender,addr)
values
(#{username},#{password},#{gender},#{addr});
</insert>
7、修改数据
修改全部字段
<update id="updateAll" >
update tb_user
set user_name = #{username},
password = #{password},
gender = #{gender},
addr = #{addr}
where id = #{id};
</update>
//接收参数
String username = "张明杨";
String password = "124589";
String gender = "女";
String addr = "广西";
Integer id = 7;
//封装新的对象
User user = new User(id,username,password,gender,addr);
//4、执行接口方法(执行SQL语句) 通过接口方法执行SQL语句
int count = usermapper.updateAll(user);
修改动态字段
使用Mybatis提供的<set标签> 只修改部分字段
<update id="updatePart">
update tb_user
<set>
<if test="username != null and username != ''">
user_name = #{username},
</if>
<if test="password != null and password != ''">
password = #{password},
</if>
<if test="gender != null and gender != ''">
gender = #{gender},
</if>
<if test="addr != null and addr != ''">
addr = #{addr},
</if>
</set>
where id = #{id};
</update>
//接收参数
String username = "张明杨";
String password = "124589";
String gender = "女";
String addr = "广西";
Integer id = 8;
//封装新的对象
User user = new User();
user.setUsername(username);
//user.setPassword(password);
//user.setGender(gender);
user.setId(id);
user.setAddr(addr);
//4、执行接口方法(执行SQL语句) 通过接口方法执行SQL语句
int count = usermapper.updatePart(user);
System.out.println(count);
8、删除数据
删除一个
批量删除
//9、批量删除
//使用@Param注解将这个ids数组命名,传到sql语句中
int deleteByIds(@Param("ids") int[] ids);
<!--
在Mybatis中会将数组参数封装成一个Map集合
键:数组 值:数组参数id对应的实体类对象
*默认key的名称为 array
*通过@Param注解可以改变map集合的默认key的名称
-->
<delete id="deleteByIds">
delete from tb_user where id
in
<!--根据数组内容生成对应数量的占位符-->
<!--collection:对应的数组名称 item:相当于循环中获取到的元素 separator:元素之间的分隔符 open:以什么开头 close:以什么结尾-->
<foreach collection="ids" item="id" separator="," open="(" close=");">
#{id}
</foreach>
</delete>
//3、获取Mapper接口的代理对象
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
//接收参数
int[] ids = {6};
//4、执行接口方法(执行SQL语句) 通过接口方法执行SQL语句
int count = usermapper.deleteByIds(ids);
System.out.println(count);
9、Mybatis使用注解完成增删改查
定义接口时使用注解,注解中写入sql语句
//注解开发简单SQL语句
//注解添加数据
@Insert("insert into tb_user(user_name,password,gender,addr) values (#{username},#{password},#{gender},#{addr})")
int addAll2(User user);
//接收参数
String username = "张三";
String password = "1221421";
String gender = "男";
String addr = "徽";
User user = new User(username,password,gender,addr);
//4、执行接口方法(执行SQL语句) 通过接口方法执行SQL语句
int count = usermapper.addAll2(user);
sqlSession.commit();
System.out.println(count);