文章目录
- eclipse中新建maven project
配置pom.xml - 框架原理初步了解
- 一个小栗子步骤:
全局配置
数据库准备
实体类pojo
实体类映射
数据库操作dao及实现类
全局中配置映射文件
打开会话
测试执行sql - xml配置部分解读
- 动态代理
1.eclipse中新建maven project
暂无
2.配置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.0</modelVersion>
<groupId>com</groupId>
<artifactId>ADemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<!-- mybatis学习(一) -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
</dependencies>
<!-- 为此项目指定jdk版本 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-complie</artifactId>
<version>3.1</version>
<configuration>
<encoding>utf-8</encoding>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
3.框架原理初步了解
–暂无
4.步骤
在src/main/resource下配置此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>
<!-- <properties>
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="mysql://localhost:3306" />
<property name="username" value="root" />
<property name="password" value="123456" />
配置了这个可以直接用el表达式引用
如下id为development的环境
</properties> -->
<!-- 环境 可以配置多个 default:指定采用哪个环境 -->
<environments default="test">
<!-- id:唯一表示 -->
<environment id="test">
<!-- 事物管理器,jdbc类型的事务管理器 -->
<transactionManager type="jdbc" />
<!-- 数据源 池类型 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver" />
<!-- 我用的mysql8.0.18 -->
<property name="url"
value="jdbc:mysql://localhost:3306/astudy?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
<!-- 上面配置了properties -->
<!-- <environment id="development">
事物管理器,jdbc类型的事务管理器
<transactionManager type="jdbc" />
数据源 池类型
<datasource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value=${username} />
<property name="password" value=${password} />
</datasource>
</environment>
</environments>-->
</configuration>
-- ----------------------------
-- Table structure for tb_student
-- ----------------------------
DROP TABLE IF EXISTS `tb_student`;
CREATE TABLE `tb_student` (
`sid` tinyint(4) NOT NULL AUTO_INCREMENT,
`sNo` char(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`sName` char(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`sSex` char(4) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`sid`) USING BTREE,
UNIQUE INDEX `sNo`(`sNo`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tb_student
-- ----------------------------
INSERT INTO `tb_student` VALUES (1, '001', '朱志', '男');
INSERT INTO `tb_student` VALUES (2, '002', '龚亮', '男');
INSERT INTO `tb_student` VALUES (3, '003', '王鹏', '男');
INSERT INTO `tb_student` VALUES (4, '004', '小红', '女');
INSERT INTO `tb_student` VALUES (5, '005', '烛龙', '男');
INSERT INTO `tb_student` VALUES (6, '006', '白宇', '男');
INSERT INTO `tb_student` VALUES (8, '007', '油条', '男');
INSERT INTO `tb_student` VALUES (11, '008', '油条', '男');
INSERT INTO `tb_student` VALUES (12, '009', '豆浆', '女');
SET FOREIGN_KEY_CHECKS = 1;
我的pojo类属性和数据库字段是一样的 便于mybatis填充对应的信息
如果不一样 可以在dao中使用注解或者在sql中使用别名的方式等等……
package com.entity;
public class Student {
private int sid;
private String sNo;
private String sName;
private String sSex;
public Student() {
super();
}
public Student(int sid, String sNo, String sName, String sSex) {
super();
this.sid = sid;
this.sNo = sNo;
this.sName = sName;
this.sSex = sSex;
}
@Override
public String toString() {
return "Student [sid=" + sid + ", sNo=" + sNo + ", sName=" + sName + ", sSex=" + sSex + "]";
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getsNo() {
return sNo;
}
public void setsNo(String sNo) {
this.sNo = sNo;
}
public String getsName() {
return sName;
}
public void setsName(String sName) {
this.sName = sName;
}
public String getsSex() {
return sSex;
}
public void setsSex(String sSex) {
this.sSex = sSex;
}
}
提示对命名空间的一点说明:
在之前版本的 MyBatis 中,命名空间(Namespaces)的作用并不大,是可选的。 但现在,随着命名空间越发重要,你必须指定命名空间。
命名空间的作用有两个,一个是利用更长的完全限定名来将不同的语句隔离开来,同时也实现了你上面见到的接口绑定。就算你觉得暂时用不到接口绑定,你也应该遵循这里的规定,以防哪天你改变了主意。 长远来看,只要将命名空间置于合适的 Java 包命名空间之中,你的代码会变得更加整洁,也有利于你更方便地使用 MyBatis。
命名解析:为了减少输入量,MyBatis 对所有的命名配置元素(包括语句,结果映射,缓存等)使用了如下的命名解析规则。
//dao
package com.dao;
import java.util.List;
import com.entity.Student;
public interface StuDao {
/*
* 查询所有学生信息
*/
List<Student> ListAllStu();
/*
* 查询一名学生记录
*/
Student getStu(int sid);
/*
* 新增一条学生信息
*/
void addStu(Student stu);
/*
* 修改学生信息
*/
void updateStu(Student stu);
/*
*删除学生信息
*/
void deleteStu(int id);
}
//daoImpl
package com.dao.impl;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import com.dao.StuDao;
import com.entity.Student;
import com.util.MybatisUtil;
public class StuDaoImpl implements StuDao {
// 获取session
SqlSession session = MybatisUtil.getSqlSession();
/*
* 查询所有学生信息
*/
@Override
public List<Student> ListAllStu() {
return this.session.selectList("StuDaomapper.selectStus", 1);
}
/*
* 查询一条学生信息
*/
@Override
public Student getStu(int sid) {
return this.session.selectOne("StuDaomapper.selectone", sid);
}
@Override
/*
* 新增一条学生信息
*表单新增时不允许自己设置学生学号
*通过查找最大id+1? 算了。。先不写
*/
public void addStu(Student stu) {
this.session.insert("StuDaomapper.insertone",stu);
this.session.commit();
}
@Override
public void updateStu(Student stu) {
this.session.update("StuDaomapper.update", stu);
this.session.commit();
}
@Override
public void deleteStu(int id) {
this.session.delete("StuDaomapper.delete", id);
this.session.commit();
}
}
命名这个,一般是pojomapper.xml吧 看个人规范
也可以参考:mybatis官方文档
<?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="StuDaomapper">
<!-- id:唯一标识 当实体类中的属性和数据库中的字段对应时 使用resultType..parameterMap.. resultType:sql语句查询结果集的封装类型
resultMap:结果集映射?? statement:sql语句 parameterType:查询条件的参数类型 parameterMap:????? -->
<select id="selectStus" resultType="com.entity.Student">
select * from tb_student
</select>
<select id="selectone" parameterType="int" resultType="com.entity.Student">
select * from tb_student where sid = #{sid}
</select>
<insert id="insertone" parameterType="com.entity.Student">
insert into tb_student (sNo,sName,sSex)
values(#{sNo},#{sName},#{sSex})
</insert>
<update id="update" parameterType="int">
update tb_student set sNo=#{sNo},sName=#{sName},sSex=#{sSex} where sid=#{sid}
</update>
<delete id="delete" parameterType="int">
delete from tb_student where sid=#{sid}
</delete>
</mapper>
在mybati-config.xml中,节点里,新增:
<mappers>
<!-- 除了recource属性,还有class等 -->
<mapper resource="com/mapper/Student.mbm.xml" />
</mappers>
写得不太规范 可参考mybatis官方文档
也可以不从xml中构建
“每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例。”
package com.util;
import java.io.IOException;
import java.io.InputStream;
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.omg.CORBA.PUBLIC_MEMBER;
public class MybatisUtil {
private static SqlSession session;
private static SqlSessionFactory sqlSessionFactory;
static {
try {
// 指定全局配置文件
String resource = "mybatis-config.xml";
// 加载 读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
// 构建sqlSessionFactoryBuilder对象
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
/* 提供获取session的接口
* 查看官方文档:sqlSession不能被共享,所以不能放在静态区
*/
public static SqlSession getSqlSession() {
// 打开sqlSession会话 获取session对象
session = sqlSessionFactory.openSession();
return session;
}
// 关闭SqlSession连接
public static void closeSqlSession() {
if (session != null) {
session.close();
}
}
}
写的时候 是写一个方法测一个方法的
package com.dao.impl;
import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayList;
import java.util.List;
import org.junit.AfterClass;
import org.junit.jupiter.api.Test;
import com.entity.Student;
import com.util.MybatisUtil;
class StuDaoImplTest {
@Test
//查询多条数据
void testListAllStu() {
List<Student> sList = new StuDaoImpl().ListAllStu();
for (Student student : sList) {
System.out.println(student);
}
}
@Test
//查询一条数据
void testgetStu() {
Student stu = new StuDaoImpl().getStu(3);
System.out.println(stu);
}
@Test
//新增一条数据测试
void testAddStu() {
Student stu = new Student();
stu.setsName("豆浆");
stu.setsNo("009");
stu.setsSex("女");
System.out.println(stu);
new StuDaoImpl().addStu(stu);
}
@Test
//更新测试
void testupdateStu() {
Student stu = new Student();
stu.setSid(5);
stu.setsName("烤肉");
stu.setsNo("005");
stu.setsSex("女");
new StuDaoImpl().updateStu(stu);
}
@Test
//删除一条数据
void testdeleteStu() {
new StuDaoImpl().deleteStu(11);
}
@AfterClass
//关闭session会话
void close() {
MybatisUtil.closeSqlSession();
}
}
5.xml配置部分解读
- 属性(properties):
上面mybatis-config.xml已经介绍
属性可以在不止一个位置配置,那么mybatis的加载顺序:
在 properties 元素体内指定的属性首先被读取。
然后根据 properties 元素中的 resource 属性读取类路径下属性文件或根据 url 属性指定的路径读取属性文件,并覆盖已读取的同名属性。
最后读取作为方法参数传递的属性,并覆盖已读取的同名属性。
因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的是 properties 属性中指定的属性。
- 设置 settings
完整实例如下:
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
- 类型别名(typeAliases)
用于减少冗余的类限定名。有时候一个类限定名前缀可能特别长
<typeAliases>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
</typeAliases>
当这样配置时,Blog 可以用在任何使用 domain.blog.Blog 的地方。
- 事物管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type=”[JDBC|MANAGED]”):
JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。例如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
提示:如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器, 因为 Spring 模块会使用自带的管理器来覆盖前面的配置。
之前使用jdbc时,事物是默认自动提交的。要手动提交, 就
conn.setAutoCommit(false); //关闭自动提交
mybatis封装了的jdbc的默认开启事物管理的,也就是说要手动提交
先看一下官方文档给出的解释:
映射器实例
映射器是一些由你创建的、绑定你映射的语句的接口。映射器接口的实例是从 SqlSession 中获得的。因此从技术层面讲,任何映射器实例的最大作用域是和请求它们的 SqlSession 相同的。尽管如此,映射器实例的最佳作用域是方法作用域。 也就是说,映射器实例应该在调用它们的方法中被请求,用过之后即可丢弃。 并不需要显式地关闭映射器实例,尽管在整个请求作用域保持映射器实例也不会有什么问题,但是你很快会发现,像 SqlSession 一样,在这个作用域上管理太多的资源的话会难于控制。 为了避免这种复杂性,最好把映射器放在方法作用域内。下面的示例就展示了这个实践:
try (SqlSession session = sqlSessionFactory.openSession()) {
BlogMapper mapper = session.getMapper(BlogMapper.class);
// 你的应用逻辑代码
}
上述curd
传统的结构:
现在mybatis的接口动态代理机制,可以让我们无需写实现类。只需要写dao(mapper.java)即可。
但是 要限定类映射文件中的namesapce为dao接口的全类限定名
//上面的测试类 MybatisTest.java
@Test
//新增一条数据测试
void testAddStu() {
Student stu = new Student();
stu.setsName("肥牛");
stu.setsNo("010");
stu.setsSex("女");
System.out.println(stu);
//new StuDaoImpl().addStu(stu);
//动态代理
SqlSession session = MybatisUtil.getSqlSession();
StuDao stuDao = session.getMapper(StuDao.class);
stuDao.addStu(stu);
session.commit();
}