Maven
maven是一种工具
Apache Maven是一个项目管理和构建工具,主要作用如下:
1.统一项目目录结构:提供标准、统一的项目结构。
2.自动化项目构建
3.依赖管理,管理项目依赖的资源(jar包),避免版本冲突。
MyBatis
1.MyBatis是什么
MyBatis是一款优秀的框架,用于实现向数据库发送SQL语句,实现增删改查。
2.为什么要使用mybatis
当前向MySQL发送SQL语句是通过idea发送的,idea中有一个Database,通过控制窗口将SQL语句发送给数据库。
mybatis是一种框架。这个框架代码不多且简单,但不好理解。
MyBatis原本是Apache的一个开源项目iBatis,后改名为MyBatis。
用于向数据库发送SQL语句,实现增删改查。
框架可以理解为半成品的软件,框架做好以后,程序员只需在框架基础上继续进行后面的开发。
框架就是别人做一半,程序员去完成另一半。
学习框架时,重点是如何使用框架。
框架底层大量都是代理模式和反射实现的。
3.Mybatis入门
使用Mybatis操作数据库
3.1使用Mybatis向数据库保存一个User对象的步骤
1.我们要做的是把一个SQL语句使用Java平台发送到MySQL。
2.比如说有一个类User,其中有两个属性,id和name。如果想保存到MySQL中,就应该事先在MySQL中准备一张表,表中至少要有两个字段(id和name)去保存它们。
3.类无法保存变量值,要想保存得创建对象,比如User对象:id:1,name:张三。
结果就是这个对象发到MySQL中后形成一条横向的记录。
但是不能把一个对象直接发送到MySQL数据库。MySQL数据库只认识SQL语句。
4.所以需要想办法把这个对象整成一条SQL语句,把SQL语句发送到MySQL数据库。
Java中的类,对应MySQL数据库中的数据表。
对象,对应的是MySQL数据库中的一条记录。
类中的属性,对应MySQL数据表的字段。
3.2思路
1.准备数据环境(创建数据库、数据表)
2.创建工程,添加依赖
3.准备实体类(实体类要根据数据表书写):在main下写,实体类的包一般叫做domain,domain是包层次,在domain包里定义实体类,这是业界规范。
//User实体类
package com.itheima.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
//实体类——>表
//类中的属性——>表中字段
//实体类中所有的字段都要包装类型
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String name;
private Integer age;
private Integer gender;
private String phone;
}
以上三步都是学过的
比较新、重要、难的是下面两步
4.创建Mapper接口(在接口的方法上使用注解编写SQL语句)(“把快件SQL语句准备好”)
5.创建配置文件(配置数据库连接信息)(“把收货地址准备好”)
6.测试(“发货”)
用mybatis把一个User对象发送到数据库中来。
实质上就是把对象中保存的信息转换成SQL语句,把SQL语句发送到MySQL数据库。
3.2.1思路第4步:
1.在domain同级目录建立mapper包,在mapper包中创建mapper接口,在接口的方法上使用注解编写SQL语句。
2.想要实现什么功能就在接口中写什么方法,如3.1中想给数据库中保存一个User对象,那就在mapper接口中写一个保存的方法,保存方法没有返回值(只有查询方法有返回值)
mybatis规定了一个特殊符号:`#{ }`,它的作用是从方法的参数中取值赋值到SQL语句。
若方法参数是一个对象类型,则`#{ }`的{ }里写的是对象中的属性名。
3.2.2思路第5步:
创建配置文件(配置数据库连接信息),把配置文件SqlMapConfig.xml放到正式文件main包下的resources中
<!--SqlMapConfig.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>
<settings>
<!--在控制台输出发送的sql日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!--目前只关注这部分内容,它的作用就是声明要连接的数据信息-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--声明含有sql的接口所在包-->
<package name="com.itheima.mapper"/>
</mappers>
</configuration>
在配置文件中声明mapper包的位置,是为了拿到接口中的SQL语句。底层拿到SQL语句使用了反射技术。
引进mapper,底层通过反射技术找到所有接口,再找到所有接口上的注解,就找到了SQL语句。
在告诉mybatis的时候,直接把此配置文件交给mybatis即可。此配置文件中既有SQL语句,又有MySQL的地址信息。交给“快递员”(mybatis)就直接“发货”(发送给MySQL数据库)。
3.2.3思路第6步
测试类应该写在test包下的java包下
//1. 使用mybatis将user对象保存到数据库(步骤不重要, 不用记)
//1-1 读取配置文件,读成一个输入流(SqlMapConfig.xml里面是数据库的地址和一个半成品sql)
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//1-2 创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//1-3 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//1-4 获取UserMapper对象,调用方法
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//底层是代理模式,只有接口没有实现类能拿到对象,反射做不到,是代理模式,对UserMapper代理出了一个实际的对象
userMapper.save(user);
//1-5 提交事务(mybatis默认不会自动提交事务,需要手动提交)
sqlSession.commit();
//1-6 关闭连接,释放资源
sqlSession.close();
3.4 配置SQL提示
解决方案:
在配置MySQL连接时,配置上数据库名:
4.Mybatis实现增删改
4.1新增(主键返回)
4.2在mybatis框架下新增一个功能的步骤
在mybatis框架下,每增加一个功能,需要在mapper接口中新增一个方法和一条SQL语句注解,在测试类中新增一个测试方法。
总结如下:
新增功能需要如下两个步骤:
1.在mapper接口中添加方法和SQL语句
2.在测试类中添加测试方法
4.3修改
//修改(没有返回值,只有查询才有返回值)
//前面name是表中字段名 后面的name是类中属性名
@Update("update user set name=#{name},age=#{age},gender=#{gender},phone=#{phone} where id=#{id}")
void update(User user);
4.4删除
//#{} 从方法参数中取值赋值到sql
//如果方法参数是一个对象类型,则#{}写的是对象中的属性名
//如果方法参数是一个简单类型(8中基本+8种包装+String),则#{}可以随便写(但是推荐写成方法的形参)
//删除
@Delete("delete from user where id=#{id}")
void delete(Integer id);
5.抽取工具类
可以看到,测试类中重复代码量很大,要解决这个问题需要抽取工具类。
抽取工具类的思想:把重复代码放到一个地方
5.1为什么要抽取工具类
观察测试方法,可以发现,测试类中有大量重复代码。
所以要抽取一个工具类,让代码看起来更简洁。
5.2抽取工具类的步骤
1.先观察测试类,找到方法中共同的代码。
2.创建一个工具类,在类中创建静态方法,然后将公共代码提取到静态方法中。
3.使用工具类中的方法替换公共代码。
//1-1 读取配置文件,读成一个输入流
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//1-2 创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//1-3 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
以上1-1、1-2和1-3,三步都为公共代码,可以抽取为工具类。
整个代码中,只有1-4
//1-4 获取UserMapper对象,调用方法
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);//这条语句中,每次传入getMapper方法的接口的实现类对象都不同,这次是User类的mapper接口的实现类对象,操作的是User表,下次可以是Student的,所以不是公共代码
userMapper.save(user);//这条语句中,每次调用的测试方法都不同
以下1-5、1-6也为公共代码,也可以抽取为工具类。
//1-5 提交事务(mybatis默认不会自动提交事务,需要手动提交)
sqlSession.commit();
//1-6 关闭连接,释放资源
sqlSession.close();
习惯上会把抽取出来的工具类放到一个util包下,工具类名要见名知义。
将公共代码抽取成工具类之后,代码很简洁,如下图:
@Test
public void testDelete() throws IOException {
//使用mybatis将一个User对象发送到数据库中
//1.准备一个User对象(必须有id)
User user = new User();
user.setName("张三");
user.setAge(18);
user.setGender(0);
user.setPhone("13700131000");
user.setId(1);
//2.使用mybatis将一个User对象发送到数据库中
//1. 使用mybatis将user对象保存到数据库(步骤不重要, 不用记)
//SqlMapConfig.xml里面是数据库的地址和一个半成品sql
//1-1、1-2、1-3:调用工具类中的方法获取sqlSession
SqlSession sqlSession = MybatisUtil.getSqlSession();
//1-4 获取UserMapper对象,调用方法
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
userMapper.delete(1);
//1-5、1-6:调用工具类中的方法提交事务并且释放资源
MybatisUtil.commitAndClose(sqlSession);
}
一旦碰到工厂、xx池,在项目中一定要保证是单例的,比如线程池。
工厂应该只有一个,每次使用工具时就新创建一个工厂是不合理的。
因此要保证1-1和1-2这两句代码只执行一次。
可以用单例实现,也可以用静态代码块实现。
在类加载时加载,且仅加载一次。
package com.itheima.util;
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 java.io.InputStream;
public class MybatisUtil {
//提升SqlSessionFactory作用域
private static SqlSessionFactory sqlSessionFactory = null;//静态的只能访问静态的,所以此处也得用static修饰
//作为工具类,要求私有构造器
private MybatisUtil(){}
//静态代码块
static {
try {
//1-1 读取配置文件,读成一个输入流
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//1-2 创建SqlSessionFactory对象
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}catch (Exception e){
//程序抛出异常 jvm默认是打印并退出
throw new RuntimeException("文件加载失败");
}
}
//获取sqlSession
public static SqlSession getSqlSession() {
//此处有一个异常,对于工具类来说,有异常最好不要往外抛,最好用try...catch处理异常
//public static 返回值 方法名(参数){
//1-3 获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
return sqlSession;
}
//提交事务、释放资源
//工具类中只要是带参数的方法一定要判空,如果有人故意捣乱传null,工具类会出现空指针异常
public static void commitAndClose(SqlSession sqlSession){
if(sqlSession!=null){
//1-5 提交事务(mybatis默认不会自动提交事务,需要手动提交)
sqlSession.commit();
//1-6 关闭连接,释放资源
sqlSession.close();
}
}
}