什么是框架?
个人理解:框架是由别人为我们提供的一个“大”的工具类,我们需要遵循该工具类的规则下,完成自己的功能。
例如:工具类只是关心class
文件,就需要找到相应的jar
包,类似于commons-fileupload.jar
为什么使用框架?
在没有框架(有规则的工具类),我们在进行数据库操作的时候,每个程序员对CRUD的封装方式和方法都是不同.
这样没有规则,当程序员离开的时候,接手的程序员需要重新进行学习,增加学习成本,不利于公司的效率。
如何学习框架?
jar
包,里面包含class文件(Maven进行下载)xml文件
和javaConfig文件
)MyBatis 是一款优秀的持久层框架
,它支持自定义 SQL、存储过程以及高级映射
。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
持久层框架
:持久层将数据保存到数据库(数据访问层)简单映射
和高级映射
ORM框架(Object Relationship Mapping)
:数据库中查询的结果集需要通过一个文件描述,可以转换成Java对象(POJO===>框架中的术语持久化对象:对应数据库中记录
)关于持久层框架和ORM框架:MyBatis框架、Hibernate框架、JFinal框架等等
基础操作:CRUD(Create Retrieval Update Delete
)
pom.xml内容:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.yuegroupId>
<artifactId>mybatis01artifactId>
<version>1.0-SNAPSHOTversion>
<properties>
<maven.compiler.source>13maven.compiler.source>
<maven.compiler.target>13maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.48version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.5version>
dependency>
dependencies>
project>
主要完成包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/yue_mybatis"/>
<property name="username" value="root"/>
<property name="password" value=""/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="mapper/SqlMapper.xml"/>
mappers>
configuration>
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mysql.student">
<insert id="add01">
INSERT INTO student(student_name,student_sex,age,birthday)
VALUES ('天枢','男生',18,'1990-10-10')
insert>
<insert id="add02">
INSERT INTO student(student_name,student_sex,age,birthday)
VALUES ('星河','女生',19,'1991-10-10')
insert>
mapper>
固定
操作,类似于JDBC的固定操作,按步就班package com.yue;
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.IOException;
import java.io.InputStream;
public class A_固定套路操作 {
public static void main(String[] args) throws IOException {
//1.指定核心配置文件位置
String path = "config/mybatis-config.xml";
//2.读取核心配置文件内容
InputStream in = Resources.getResourceAsStream(path);
//3.建立SqlSession工厂(生产SqlSession对象)
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//4.获取SqlSession对象(主要作用:连接数据库,执行数据库操作)
SqlSession session = factory.openSession();
//5.可变:执行定制的sql语句,通过坐标进行查找“namespace.id”的形式,返回值为影响的行数
int row = session.insert("com.mysql.student.add01");
System.out.println("row = " + row);
row = session.insert("com.mysql.student.add02");
System.out.println("row = " + row);
//6.因为是变更语句,改变数据库的操作需要手动提交事务
session.commit();
}
}
CREATE TABLE `yf06_mybatis`.`student` (
`student_id` int(11) NOT NULL AUTO_INCREMENT,
`student_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`student_sex` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`age` int(11) NULL DEFAULT NULL,
`birthday` date NULL DEFAULT NULL,
PRIMARY KEY (`student_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
前提:设置面向接口编程
1.原生方式:需要自己完成实现
2.接口方式:MyBatis框架自动创建实现类,根据映射文件创建
接口文件:
package com.dao;
public interface StudentDao {
void insert01() throws Exception;
void insert02() throws Exception;
}
由程序员自己决定使用哪个SQL语句和对应的方法SqlSession下insert/update/delete/selectOne/selectList
实现类:
package com.dao;
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 StudentDaoImpl implements StudentDao {
@Override
public void insert01() throws Exception {
//1.指定核心配置文件位置
String path = "config/mybatis-config.xml";
//2.读取核心配置文件内容
InputStream in = Resources.getResourceAsStream(path);
//3.建立SqlSession工厂(生产SqlSession对象)
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//4.获取SqlSession对象(主要作用:连接数据库,执行数据库操作)
SqlSession session = factory.openSession();
//5.可变:执行定制的sql语句,通过坐标进行查找“namespace.id”的形式,返回值为影响的行数
int row = session.insert("com.mysql.student.add01");
//6.因为是变更语句,改变数据库的操作需要手动提交事务
session.commit();
}
@Override
public void insert02() throws Exception{
//1.指定核心配置文件位置
String path = "config/mybatis-config.xml";
//2.读取核心配置文件内容
InputStream in = Resources.getResourceAsStream(path);
//3.建立SqlSession工厂(生产SqlSession对象)
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//4.获取SqlSession对象(主要作用:连接数据库,执行数据库操作)
SqlSession session = factory.openSession();
//5.可变:执行定制的sql语句,通过坐标进行查找“namespace.id”的形式,返回值为影响的行数
int row = session.insert("com.mysql.student.add02");
//6.因为是变更语句,改变数据库的操作需要手动提交事务
session.commit();
}
}
package com.yue;
import com.dao.StudentDao;
import com.dao.StudentDaoImpl;
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.IOException;
import java.io.InputStream;
public class B_原生方式不推荐 {
public static void main(String[] args) throws Exception {
StudentDao studentDao = new StudentDaoImpl();
studentDao.insert01();
studentDao.insert02();
}
}
原生方式增加其他程序员阅读成本,所以将查找SQL语句和实现类的方式,进行更加简单的设计,但是需要遵循特定的规则
约定优于配置
,才会跟快速的开发
使用方式:
insert/update/delete
方法,int类型是返回的影响行数selectOne
)、集合(selectList
)代码:
package com.mapper;
public interface StudentMapper {
int add();
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mapper.StudentMapper">
<insert id="add">
INSERT INTO student(student_name,student_sex,age,birthday)
VALUES ('摇光','女',18,'1990-10-10')
insert>
mapper>
package com.yue;
import com.dao.StudentDao;
import com.dao.StudentDaoImpl;
import com.mapper.StudentMapper;
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 C_接口方式无实现类 {
public static void main(String[] args) throws Exception {
//1.指定核心配置文件位置
String path = "config/mybatis-config.xml";
//2.读取核心配置文件内容
InputStream in = Resources.getResourceAsStream(path);
//3.建立SqlSession工厂(生产SqlSession对象)
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//4.获取SqlSession对象(主要作用:连接数据库,执行数据库操作)
SqlSession session = factory.openSession();
//5.可变:动态实例接口回调
/**底层相当根据映射文件构建:StudentMapper studentMapper = new StudentMapperImpl()*/
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
int row = studentMapper.add();
//6.因为是变更语句,改变数据库的操作需要手动提交事务
session.commit();
}
}
重要:
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
:底层相当根据映射文件构建:StudentMapper studentMapper = new StudentMapperImpl()
Exception in thread "main" org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.yue.mapper.StudentMapper.add
java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.yue.mapper.StudentMapper.add. please check mapper/StudentMapper.xml and mapper/StudentMapper.xml
java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.yue.mapper.StudentMapper.add. please check mapper/SqlMapper.xml and mapper/StudentMapper.xml
方便在控制台查看信息使用,在核心配置文件mybatis-config.xml
设置:
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
settings>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/yue_mybatis"/>
<property name="username" value="root"/>
<property name="password" value=""/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="mapper/StudentMapper.xml"/>
mappers>
configuration>
Map对象或者自定义Java对象
基本数据类型、引用数据类型
数组或者集合
public interface StudentMapper {
void add02(Map<String,Object> recordMap);
}
parameterType:传递参数的类型(可以被自动识别
) parameterMap(不会使用,废弃状态)
推荐使用#{Map中的KEY或者类中的属性}
:该方式默认情况使用PrepareStatement(预处理方式)处理
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mapper.StudentMapper">
<insert id="add02" parameterType="java.util.Map">
INSERT INTO student(student_name,student_sex,age,birthday)
VALUES
(#{name},#{sex},#{age},NOW())
insert>
mapper>
package com.test;
import com.mapper.StudentMapper;
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.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class A_获取Map数据 {
public static void main(String[] args) throws IOException {
String path = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(path);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = factory.openSession();
//动态实例化
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
//传递数据
//1.接口方式
Map<String,Object> dataMap = new HashMap<>();
dataMap.put("name","北斗");
dataMap.put("age",10);
dataMap.put("sex","男");
studentMapper.add02(dataMap);
//2.原生方式
dataMap = new HashMap<>();
dataMap.put("name","紫薇");
dataMap.put("age",10);
dataMap.put("sex","男");
sqlSession.insert(StudentMapper.class.getName()+".add02",dataMap);
//手动提交
sqlSession.commit();
}
}
接口:
public interface StudentMapper {
void add01();
void add02(Map<String,Object> recordMap);
void add03(Student student);
}
student类:
package com.model;
import java.util.Date;
public class Student {
private Integer studentId;
private String studentName;
private String studentSex;
private Integer age;
private Date birthday;
public Integer getStudentId() {
return studentId;
}
public void setStudentId(Integer studentId) {
this.studentId = studentId;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public String getStudentSex() {
return studentSex;
}
public void setStudentSex(String studentSex) {
this.studentSex = studentSex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Student{" +
"studentId=" + studentId +
", studentName='" + studentName + '\'' +
", studentSex='" + studentSex + '\'' +
", age=" + age +
", birthday=" + birthday +
'}';
}
}
映射文件:
<insert id="add03" parameterType="com.model.Student">
INSERT INTO student(student_name,student_sex,age)
VALUES
(#{studentName},#{studentSex},#{age});
insert>
测试文件:
package com.test;
import com.mapper.StudentMapper;
import com.model.Student;
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.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class B_获取自定义对象 {
public static void main(String[] args) throws IOException {
String path = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(path);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = factory.openSession();
//动态实例化
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
//传递数据
//1.接口方式
Student student = new Student();
student.setStudentName("南极");
student.setStudentSex("男");
student.setAge(18);
studentMapper.add03(student);
//2.原生方式
student = new Student();
student.setStudentName("北极");
student.setStudentSex("女");
student.setAge(18);
sqlSession.insert(StudentMapper.class.getName()+".add03",student);
//手动提交
sqlSession.commit();
}
}
添加、更新操作的时候,我们有的时候需要添加完毕之后,将生成的自动增长主键返回
直接输出时主键值为空
useGeneratedKeys
:是否使用自动增长的主键keyProperty
:将主键值赋值给哪个属性
<insert id="add04" parameterType="com.model.Student"
useGeneratedKeys="true" keyProperty="studentId">
INSERT INTO student(student_name,student_sex,age)
VALUES
(#{studentName},#{studentSex},#{age});
insert>
再次输出:
传递的是一个形参并且是单个值,#{任意名称,最好做到见名知意}
public interface StudentMapper {
void update01(Integer age);
}
<insert id="updata01" parameterType="java.lang.Integer">
UPDATE student SET age = #{student} WHERE age IS NULL
insert>
package com.test;
import com.mapper.StudentMapper;
import com.model.Student;
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.IOException;
import java.io.InputStream;
public class D_单个值 {
public static void main(String[] args) throws IOException {
String path = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(path);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = factory.openSession();
//动态实例化
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
studentMapper.updata01(28);
//手动提交
sqlSession.commit();
}
}
当形参个数多于一个,不能再设置parameterType属性,MyBatis自动识别
当形参个数多于一个,#{这里的名称不能自己指定,应该用arg0,arg1…等等表示,释义如下}
若是自己指定#{}名称,则报错:
org.apache.ibatis.binding.BindingException: Parameter 'sex' not found. Available parameters are [arg1, arg0, param1, param2]
(#{sex}没有找到)
arg0…parm1…释义:
arg0 第1形参KEY arg1 第2个形参KEY arg2 第3个形参KEY.....argN第N+1个形参KEY
param1 第1形参KEY param2 第2个形参KEY param 3 第3个形参KEY.....paramN第N个形参KEY
上述两者为默认方法,可读性差
推荐:@Param
指定key
public interface StudentMapper {
void update02(Integer studentId,String sex);
void update03(Integer studentId,String studentName);
void update04(@Param("id") Integer studentId,@Param("age") Integer age);
}
<update id="update02">
UPDATE student SET student_sex=#{arg1} WHERE student_id=#{arg0}
update>
<update id="update03">
UPDATE student SET student_name=#{param2} WHERE student_id=#{param1}
update>
<update id="update04">
UPDATE student SET age=#{age} WHERE student_id=#{id}
update>
public class E_多个形参 {
public static void main(String[] args) throws IOException {
String path = "mybatis-config.xml";
InputStream in =Resources.getResourceAsStream(path);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in) ;
SqlSession sqlSession = factory.openSession();
//实例化
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
studentMapper.update02(7,"女生");
studentMapper.update03(4,"星月");
studentMapper.update04(5,19);
sqlSession.commit();
sqlSession.close();
}
}
错误写法:#{idStr}
public interface StudentMapper {
void delete(String str);
}
<insert id="delete" parameterType="java.lang.String">
DELETE FROM student WHERE student_id IN #{idStr}
insert>
package com.test;
import com.mapper.StudentMapper;
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.IOException;
import java.io.InputStream;
public class E_模拟复选框删除 {
public static void main(String[] args) throws IOException {
String path = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(path);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = factory.openSession();
//动态实例化
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
int[] array = {25,26};
StringBuilder sb = new StringBuilder();
for (int val : array) {
sb.append(val);
sb.append(",");
}
//去掉最后一个`,`
sb.deleteCharAt(sb.length()-1);
studentMapper.delete(sb.toString());
//手动提交
sqlSession.commit();
}
}
<!--删除-->
<insert id="delete" parameterType="java.lang.String">
DELETE FROM student WHERE student_id IN (${idStr})
</insert>
#{}
和${}
的区别#{}:使用预处理方式处理传递数据,不容易造成SQL注入的情况
${}:使用Statement的方式处理,拼接到SQL语句,并且需要我们个人处理数据
<insert id="add04" parameterType="com.model.Student"
useGeneratedKeys="true" keyProperty="studentId"
>
INSERT INTO student (student_name,student_sex,age)
VALUES
(#{studentName},#{studentSex},#{age})
</insert>
<insert id="add05" parameterType="com.model.Student"
useGenera tedKeys="true" keyProperty="studentId"
>
INSERT INTO student (student_name,student_sex,age)
VALUES
('${studentName}','${studentSex}',${age})
</insert>
==> Preparing: INSERT INTO student (student_name,student_sex,age) VALUES (?,?,?)
==> Parameters: 关羽123(String), 男生(String), 22(Integer)
<== Updates: 1
==> Preparing: INSERT INTO student (student_name,student_sex,age) VALUES ('曹操123','男生',22)
==> Parameters:
<== Updates: 1