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中可以解决此问题。
1、创建maven工程
(1)打开Eclipse,File-New,新建maven工程,过程如图:
接下来以此输入:
Group Id 中输入项目的基本包名。
Artifact Id 中输入项目名。
Version 中的值默认就行,不进行选择。
Package 中写的是默认生成的一个包名,不写也可以。
接着点击完成就可以了
工程目录如下图:
完整的项目结构:
2、引入Mybatis及其他依赖
在 pom.xml 文件中添加 Mybatis3.4.6 的坐标,如下:
4.0.0com.xhbjavaMybatis01war0.0.1-SNAPSHOTMybatis01 Maven Webapphttp://maven.apache.orgorg.mybatismybatis3.4.6mysqlmysql-connector-java8.0.15log4jlog4j1.2.12junitjunit3.8.1testMybatis01
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
*/
ListfindAll();
}
5、编写持久层接口的映射文件 IUserDao.xml
select * from user
6、编写 SqlMapConfig.xml 配置文件
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.使用代理对象执行方法
Listusers = userDao.findAll();
// 6.打印测试信息
for (User user : users) {
System.out.println(user);
}
// 7.释放资源
session.close();
in.close();
}
}
9.遇到的问题
mysql版本
此时mysql连接如下:
运行测试类报错:
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.(XPathParser.java:125)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.(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)
解决办法:
修改数据库配置
三、基于注解的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")
ListfindAll();
}
2.修改SqlMapConfig.xml
3.删除IUserDao.xml