MyBatis快速入门
MyBatis概述
MyBatis是Apache的一个开源项目iBatis,2010年这个项目由Apache software foundation迁移到了google code,并且改名为MyBatis,2013年11月迁移到github。
MyBatis是一个实现了数据持久化的开源框架,简单理解就是对JDBC进行封装。
ORMapping:Object Relationship Mapping-------对象关系映射
对象指面向对象
关系指关系型数据库
映射指Java到MySQL的映射,开发者可以以面向对象的思想来管理数据库。
MyBatis的优点
- ⭐与JDBC相比,减少了50%以上的代码量
- ⭐MyBatis是最简单的持久化框架,小巧并且简单易学
- ⭐MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,降低耦合度,便于统一管理和优化,并可重用。
- ⭐提供XML标签,支持编写动态SQL语句。
- ⭐提供映射标签,支持对象与数据库的ORM字段关系映射。
MyBatis的缺点
- ⭐SQL语句的编写工作量较大,尤其是字段多、关联表多时,更是如此。对开发人员编写SQL语句的功底有一定的要求。
- ⭐SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
MyBatis核心接口和类
目的是为了获得SqlSession对象。
通过SqlSessionFactoryBuilder中的build()方法得到SqlSessionFactory。
再通过SqlSessionFactory中的openSession()方法最终获取SqlSession对象。
MyBatis的开发方式
- 使用原生接口
- MapPer代理实现自定义接口
如何使用
1.新建Maven工程,porm.xml
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
</dependencies>
- 新建数据表
CREATE TABLE t_account(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(11),
PASSWORD VARCHAR(11),
age INT);
- 新建数据表对应的实体类Account
public class Account {
private long id;
private String username;
private String password;
private int age;
public Account(long id, String username, String password,int age) {
this.id = id;
this.username = username;
this.password = password;
this.age = age;
}
}
- 创建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>
<!--配置MyBatis运行环境 -->
<environments default="development">
<environment id="development">
<!-- 配置JDBC管理事务 -->
<transactionManager type="JDBC"></transactionManager>
<!-- POOLED配置JDBC数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
</configuration>
MyBatis的开发方式
- 使用原生接口
第一步:MyBatis框架需要开发者自定义SQL语句,写在Mapper.xml文件中,实际开发中,会为每个实体类创建对应的Mapper.xml,定义管理该对象数据的SQL。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"
"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
<mapper namespace="com.oyrf.fristmapper.AccountMapping">
<!-- parameterType指的是当调用save这个id的时候所传的参数 -->
<insert id="save" parameterType="com.oyrf.frist.Account">
insert into t_account(username,password,age) values(#{username},#{password},#{age})
</insert>
</mapper>
- namespace 通常设置为文件所在包+文件名的形式
- insert标签表示执行添加操作
- select标签表示执行查询操作
- update标签表示执行更新操作
- delete标签表示执行删除操作
- id是实际调用MyBatis方法是需要拥戴的参数
- parameterType是调用对应方法时参数的数据类型
第二步:要在全局配置文件config.xml中注册AccountMapper.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>
<!--配置MyBatis运行环境 -->
<environments default="development">
<environment id="development">
<!-- 配置JDBC管理事务 -->
<transactionManager type="JDBC"></transactionManager>
<!-- POOLED配置JDBC数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
<!-- 注册AccountMapper.xml-->
<mappers>
<mapper resource="com/oyrf/fristmapper/AccountMapper.xml"></mapper>
</mappers>
</configuration>
第三步:调用MyBatis的原生接口执行添加操作
package com.oyrf.test;
import com.oyrf.frist.Account;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
public class Test {
public static void main(String[] args) {
//加载MyBatis配置文件
InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
String statement = "com.oyrf.frist.Account.save";
Account account = new Account(1L,"box","1234",18);
sqlSession.insert(statement,account);
sqlSession.commit();
}
}
注意:
执行的过程可能会报以下错误:
- 第一个错误
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error building SqlSession.
### The error may exist in com/oyrf/fristmapper/AccountMapper.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/oyrf/fristmapper/AccountMapper.xml
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:80)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:64)
at com.oyrf.test.Test.main(Test.java:15)
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/oyrf/fristmapper/AccountMapper.xml
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:121)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:99)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:78)
... 2 more
Caused by: java.io.IOException: Could not find resource com/oyrf/fristmapper/AccountMapper.xml
at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:114)
at org.apache.ibatis.io.Resources.getResourceAsStream(Resources.java:100)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement(XMLConfigBuilder.java:371)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:119)
... 4 more
- 第二个错误
Fri Aug 13 00:34:52 CST 2021 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
### Cause: java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:200)
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185)
at com.oyrf.test.Test.main(Test.java:19)
Caused by: java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:127)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:95)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:87)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:61)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:71)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:76)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:862)
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:444)
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:230)
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:226)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:208)
at org.apache.ibatis.datasource.unpooled.UnpooledDataSource.doGetConnection(UnpooledDataSource.java:201)
at org.apache.ibatis.datasource.unpooled.UnpooledDataSource.doGetConnection(UnpooledDataSource.java:196)
at org.apache.ibatis.datasource.unpooled.UnpooledDataSource.getConnection(UnpooledDataSource.java:93)
at org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:404)
at org.apache.ibatis.datasource.pooled.PooledDataSource.getConnection(PooledDataSource.java:90)
at org.apache.ibatis.transaction.jdbc.JdbcTransaction.openConnection(JdbcTransaction.java:139)
at org.apache.ibatis.transaction.jdbc.JdbcTransaction.getConnection(JdbcTransaction.java:61)
at org.apache.ibatis.executor.BaseExecutor.getConnection(BaseExecutor.java:336)
at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:84)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:49)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
... 2 more
Caused by: com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:59)
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:83)
at com.mysql.cj.util.TimeUtil.getCanonicalTimezone(TimeUtil.java:128)
at com.mysql.cj.protocol.a.NativeProtocol.configureTimezone(NativeProtocol.java:2201)
at com.mysql.cj.protocol.a.NativeProtocol.initServerSession(NativeProtocol.java:2225)
at com.mysql.cj.jdbc.ConnectionImpl.initializePropsFromServer(ConnectionImpl.java:1391)
at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:993)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:852)
... 20 more
原因和解决办法:
3. 第一个错误原因是只能读resourses中的xml文件,不能读java包下的xml文件,因此要在porm.xml文件里加入以下配置:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
- 第二个错误是数据库时区的问题,在jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8加上UTC,让数据库时区和本地时区一样就可以。
OYBox的个人博客:https://oybox.github.io