一、概述
1、概述
mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身, 而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。
mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并 返回。
采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节,使我 们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。
2、 JDBC编程
(1)步骤
1>加载数据库驱动
2>创建并获取数据库链接
3>创建jdbc statement对象
4>设置sql语句
5>设置sql语句中的参数(使用preparedStatement)
6>通过statement执行sql并获取结果
7>对sql执行结果进行解析处理
8>释放资源(resultSet、preparedstatement、connection)
1 package com.xhbjava; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 import java.sql.SQLException; 8 9 /** 10 * JDBC编程测试 11 * 12 * @author Mr.wang 13 * @date 2020年1月6日 14 */ 15 public class JdbcTest { 16 17 public static void main(String[] args) { 18 // 1.数据库连接 19 Connection conn = null; 20 // 2.数据库预编译 21 PreparedStatement ps = null; 22 // 3.结果集 23 ResultSet resultSet = null; 24 try { 25 // 4.加载数据库驱动 26 Class.forName("com.mysql.jdbc.Driver"); 27 // 5.通过驱动管理类获取数据库库链接 28 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/easy_mybatis?characterEncoding=utf-8", 29 "root", "root"); 30 // 6.sql语句 31 String sql = "select * from user where username=?"; 32 // 7.获取预处理 33 ps = conn.prepareStatement(sql); 34 // 8.设置入参 35 ps.setString(1, "王小码"); 36 // 9.向数据库发出sql,执行查询,返回结果集 37 resultSet = ps.executeQuery(); 38 // 10.遍历结果集 39 while (resultSet.next()) { 40 System.out.println("id:" + resultSet.getInt("id") + "username:" + resultSet.getString("username")); 41 } 42 } catch (Exception e) { 43 e.printStackTrace(); 44 } finally { 45 // 11.关闭释放为空的资源 46 if (resultSet != null) { 47 try { 48 resultSet.close(); 49 } catch (SQLException e) { 50 // TODO Auto-generated catch block 51 e.printStackTrace(); 52 } 53 } 54 if (ps != null) { 55 try { 56 ps.close(); 57 } catch (SQLException e) { 58 // TODO Auto-generated catch block 59 e.printStackTrace(); 60 } 61 62 } 63 if (conn != null) { 64 try { 65 conn.close(); 66 } catch (SQLException e) { 67 // TODO Auto-generated catch block 68 e.printStackTrace(); 69 } 70 } 71 72 } 73 74 } 75 76 }
(3)JDBC编程存在的问题
1>数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可以解决此问题。
2>Sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java代码,sql放入xml文件中方便维护。
where 条件不一定,可能多也可能少,修改 sql 还要修改代码,系统不易维护,将sql语句及占位符号和参数全部配置在xml中可以解决此问题。
二、Mybatis入门案例
1、创建maven工程
(1)打开eclipse,File-New,新建maven工程,过程如图:
接下来以此输入:
Group Id 中输入项目的基本包名。
Artifact Id 中输入项目名。
Version 中的值默认就行,不进行选择。
Package 中写的是默认生成的一个包名,不写也可以。
接着点击完成就可以了
工程目录如下图:
完整的项目结构:
2、引入Mybatis及其他依赖
在 pom.xml 文件中添加 Mybatis3.4.6 的坐标,如下:
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.xhbjava</groupId> <artifactId>Mybatis01</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>Mybatis01 Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.15</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>Mybatis01</finalName> </build> </project>
3、编写 User 实体类
package com.xhbjava.domain; import java.io.Serializable; import java.util.Date; /** * User类 * * @author Mr.wang * @date 2020年1月7日 */ public class User implements Serializable { private static final long serialVersionUID = 1L; private Integer id; private String username; private Date birthday; private String sex; private String address; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; }
@Override public String toString() { return "User [id=" + id + ", username=" + username + ", birthday=" + birthday + ", sex=" + sex + ", address=" + address + "]"; }
}
4、编写持久层接口IUserDao
package com.xhbjava.dao; import java.util.List; import com.xhbjava.domain.User; /** * 持久层 * * @author Mr.wang * @date 2020年1月7日 */ public interface IUserDao { /** * 查询所有用户 * @return */ List<User> findAll(); }
5、编写持久层接口的映射文件 IUserDao.xml
<?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="com.xhbjava.dao.IUserDao"> <select id="findAll" resultType="com.xhbjava.domain.User"> select * from user </select> </mapper>
6、编写 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> <!-- 配置环境 --> <environments default="mysql"> <!-- 配置mysql环境 --> <environment id="mysql"> <!-- 配置事务类型 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/easy_mybatis?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> <!-- 配置映射文件 --> <mappers> <mapper resource="com/xhbjava/dao/IUserDao.xml" /> </mappers> </configuration>
7、加入log4j配置文件
8、编写测试类
package com.xhbjava.test; import java.io.IOException; import java.io.InputStream; import java.util.List; 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 com.xhbjava.dao.IUserDao; import com.xhbjava.domain.User; /** * 测试类 * * @author Mr.wang * @date 2020年1月7日 */ public class MybatisTest { public static void main(String[] args) throws IOException { // 1.读取配置文件 InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); // 2.创建SqlSessionFactory工厂 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(in); // 3.使用工厂生产SqlSession对象 SqlSession session = factory.openSession(); // 4.使用SqlSession创建Dao接口代理对象 IUserDao userDao = session.getMapper(IUserDao.class); // 5.使用代理对象执行方法 List<User> users = userDao.findAll(); // 6.打印测试信息 for (User user : users) { System.out.println(user); } // 7.释放资源 session.close(); in.close(); } }
9.遇到的问题
mysql版本
此时mysql连接如下:
<property name="url" value="jdbc:mysql://localhost:3306/easy_mybatis?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT" />
运行测试类报错:
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException: ### Error building SqlSession. ### Cause: org.apache.ibatis.builder.BuilderException: Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 16; columnNumber: 103; 对实体 "useUnicode" 的引用必须以 ';' 分隔符结尾。 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.xhbjava.test.MybatisTest.main(MybatisTest.java:28) Caused by: org.apache.ibatis.builder.BuilderException: Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 16; columnNumber: 103; 对实体 "useUnicode" 的引用必须以 ';' 分隔符结尾。 at org.apache.ibatis.parsing.XPathParser.createDocument(XPathParser.java:259) at org.apache.ibatis.parsing.XPathParser.<init>(XPathParser.java:125) at org.apache.ibatis.builder.xml.XMLConfigBuilder.<init>(XMLConfigBuilder.java:82) at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:77) ... 2 more Caused by: org.xml.sax.SAXParseException; lineNumber: 16; columnNumber: 103; 对实体 "useUnicode" 的引用必须以 ';' 分隔符结尾。 at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203) at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:177) at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:441) at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368) at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1436) at com.sun.org.apache.xerces.internal.impl.XMLScanner.scanAttributeValue(XMLScanner.java:890) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanAttribute(XMLDocumentFragmentScannerImpl.java:1547) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1319) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2786) at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606) at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777) at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243) at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:348) at org.apache.ibatis.parsing.XPathParser.createDocument(XPathParser.java:257)
解决办法:
修改数据库配置
<property name="url" value="jdbc:mysql://localhost:3306/easy_mybatis?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT" />
三、基于注解的Mybatis入门案例
我们在上个例子基础上进行修改实现。
1.在持久层接口中添加注释
package com.xhbjava.dao; import java.util.List; import org.apache.ibatis.annotations.Select; import com.xhbjava.domain.User; /** * 持久层 * * @author Mr.wang * @date 2020年1月7日 */ public interface IUserDao { /** * 查询所有用户 * @return */ @Select("select * from user") List<User> findAll(); }
2.修改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> <!-- 配置环境 --> <environments default="mysql"> <!-- 配置mysql环境 --> <environment id="mysql"> <!-- 配置事务类型 --> <transactionManager type="JDBC"></transactionManager> <!-- 配置数据源 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/easy_mybatis?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> <!-- 配置映射文件 --> <mappers> <mapper class="com.xhbjava.dao.IUserDao" /> </mappers> </configuration>
3.删除IUserDao.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><!-- 配置环境 --><environments default="mysql"><!-- 配置mysql环境 --><environment id="mysql"><!-- 配置事务类型 --><transactionManager type="JDBC"></transactionManager><!-- 配置数据源 --><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver" /><property name="url" value="jdbc:mysql://localhost:3306/easy_mybatis?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT" /><property name="username" value="root" /><property name="password" value="root" /></dataSource></environment></environments><!-- 配置映射文件 --><mappers><mapper resource="com/xhbjava/dao/IUserDao.xml" /></mappers></configuration>