什么是 MyBatis ?
MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
理解:基于Java持久层框架,内部封装了jdbc,开发者只需要关系sql语句本身。
采用ORM的思想解决了实体和数据库映射的问题,对JDBC进行了封装,同时屏蔽了jdbc API底层访问细节。
ORM:将数据库表和实体类及实体类的属性对应起来,通过操作实体类就实现数据库的操作。
注意:实体类 的属性与数据库表 的字段名一一对应
一,三层架构
1,视图层:展示数据
2,业务层:处理业务需求
3,持久层:与数据进行交互
二,mybatis入门
1,步骤
1.1,创建maven工程并导入坐标
1.2,创建实体类和dao接口
1.3,创建mybatis的主配置文件
SqlMapConifg.xml
1.4,创建映射配置文件
IUserDao.xml
2,注意事项:
第一:创建IUserDao.xml和IUserDao.java时文件的路径要一致
第二:包在创建:com.itheiam.doa是三级目录
目录在创建时:com.itheiam.doa是一级目录·
第三:mybatis的映射配置文件位置必须和dao接口的包结构相同
第四:映射配置文件的mapper标签的namespace属性的取值必须是dao接口的全限定类
第五,映射配置文件的操作配置(select等)id属性的取值必须是dao接口的方法名
第六:满足以上要求就不用实现对应的接口
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(); for(User user:users) { System.out.println(user); } //6.释放资源 session.close(); in.close(); }
注意:1.读取配置文件时用的路径不要使用绝对路径,也不要使用相对路径
使用类加载器,只能读取类路径的配置文件,或者,使用ServlerContext对象的getRealPath()
2.构建者模式:把对象的创建细节隐藏,让使用者直接调用方法即可拿到对象。
3.工厂模式:优势:解耦降低类之间的依赖关系
4.代理模式:优势:不修改源码的基础上对已有的方法增强
三,解析mybatis框架的原理
核心:创建代理对象,实现查询所有。
实例一
1.主配置文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> 3 4 <!-- mybatis的主配置文件 --> 5 <configuration> 6 <environments default="mysql"> 7 <!-- 配置mysql的环境 --> 8 <environment id="mysql"> 9 <transactionManager type="JDBC" > 10 </transactionManager> 11 <dataSource type="POOLED"> 12 <property name="driver" value="com.mysql.jdbc.Driver" /> 13 <property name="url" value="jdbc:mysql://localhost:3306/db_java" /> 14 <property name="username" value="root" /> 15 <property name="password" value="" /> 16 </dataSource> 17 </environment> 18 </environments> 19 <!-- 指定映射配置文件,即每个dao独立的配置 --> 20 <mappers> 21 <mapper resource="com/dao/IUserDao.xml"/> 22 </mappers> 23 24 </configuration>
2,mapper文件。注意:要与对应的dao接口文件的路径对应
IUserDao.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.dao.IUserDao"> 6 <!-- 配置查询所有 --> 7 <select id="findAll" resultType="com.model.User"> 8 <!-- 返回值也要写全限定的类名 --> 9 select * from user; 10 </select> 11 12 <!-- 保存操作 --> 13 <insert id="saveUser" parameterType="com.model.User"> 14 <!-- 参数类型也要写全限定的类名 --> 15 insert into user (name) values(#{name}); 16 <!--#{}中的变量是对应的model中的User类的属性的getter方法的名称,但是省略了get,同时是小写 --> 17 </insert> 18 </mapper>
3.com.dao.IUserDao.java
1 package com.dao; 2 3 import java.util.List; 4 5 import com.model.User; 6 7 public interface IUserDao { 8 public List<User> findAll(); 9 void saveUser(User user); 10 }
4,com.model.User.java
1 package com.model; 2 3 import java.io.Serializable; 4 5 public class User implements Serializable{ 6 private Integer id; 7 private String name; 8 public Integer getId() { 9 return id; 10 } 11 public void setId(Integer id) { 12 this.id = id; 13 } 14 public String getName() { 15 return name; 16 } 17 public void setName(String name) { 18 this.name = name; 19 } 20 @Override 21 public String toString() { 22 return "User [id=" + id + ", name=" + name + "]"; 23 } 24 25 }
注意: 要继承Serializable接口
5.pom.xml
1 <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 2 <modelVersion>4.0.0</modelVersion> 3 <groupId>mybatis</groupId> 4 <artifactId>com</artifactId> 5 <version>0.0.1-SNAPSHOT</version> 6 <name>day1</name> 7 8 <dependencies> 9 <dependency> 10 <!--一般情况下,maven是通过groupId、artifactId、version这三个元素值(俗称坐标)来检索该构件, 然后引入你的工程。如果别人想引用你现在开发的这个项目(前提是已开发完毕并发布到了远程仓库),--> 11 <!--就需要在他的pom文件中新建一个dependency节点,将本项目的groupId、artifactId、version写入, maven就会把你上传的jar包下载到他的本地 --> 12 <groupId>org.mybatis</groupId> 13 <artifactId>mybatis</artifactId> 14 <version>3.4.5</version> 15 </dependency> 16 <dependency> 17 <groupId>mysql</groupId> 18 <artifactId>mysql-connector-java</artifactId> 19 <version>5.1.6</version> 20 </dependency> 21 <dependency> 22 <groupId>log4j</groupId> 23 <artifactId>log4j</artifactId> 24 <version>1.2.12</version> 25 </dependency> 26 <dependency> 27 <groupId>junit</groupId> 28 <artifactId>junit</artifactId> 29 <version>4.10</version> 30 </dependency> 31 32 33 34 35 </dependencies> 36 37 </project>
6.test对应的代码com.test.java
com.dao.test
1 package com.dao.test; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.List; 6 7 import org.apache.ibatis.io.Resources; 8 import org.apache.ibatis.session.SqlSession; 9 import org.apache.ibatis.session.SqlSessionFactory; 10 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 11 import org.junit.After; 12 import org.junit.Before; 13 import org.junit.Test; 14 import org.junit.experimental.theories.suppliers.TestedOn; 15 16 import com.dao.IUserDao; 17 import com.model.User; 18 19 public class MybatisTest { 20 private InputStream in; 21 private SqlSession sqlSession; 22 private IUserDao userDao; 23 24 @Before //用于在测试方法之前执行 25 public void init() throws IOException { 26 //1.读取配置文件 27 in=Resources.getResourceAsStream("SqlMapConfig.xml"); 28 29 //2.创建SqlSessionFactory工厂 30 SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder(); 31 SqlSessionFactory factory=builder.build(in); 32 //3.使用工厂生产SqlSession对象 33 sqlSession=factory.openSession(); 34 //4.使用SqlSession创建Dao接口的代理对象 35 userDao=sqlSession.getMapper(IUserDao.class); 36 37 38 39 } 40 41 @After //用于在测试之后 42 public void destory() throws IOException { 43 //提交事务 44 sqlSession.commit(); 45 //6.释放资源 46 sqlSession.close(); 47 in.close(); 48 } 49 50 @Test 51 public void findAll() throws IOException { 52 //1.读取配置文件 53 /* 54 * InputStream in=Resources.getResourceAsStream("SqlMapConfig.xml"); 55 * 56 * //2.创建SqlSessionFactory工厂 SqlSessionFactoryBuilder builder=new 57 * SqlSessionFactoryBuilder(); SqlSessionFactory factory=builder.build(in); 58 * //3.使用工厂生产SqlSession对象 SqlSession session=factory.openSession(); 59 * //4.使用SqlSession创建Dao接口的代理对象 IUserDao 60 * userDao=session.getMapper(IUserDao.class); 61 */ 62 63 //5.使用代理对象执行方法 64 List<User> users=userDao.findAll(); 65 for(User user:users) { 66 System.out.println(user); 67 } 68 69 /* 70 * //6.释放资源 session.close(); in.close(); } 71 */ 72 } 73 @Test 74 public void testSaveAll() { 75 User user=new User(); 76 user.setName("仙女"); 77 78 //执行保存方法 79 userDao.saveUser(user); 80 81 } 82 83 }
注意:1,在测试的时候的init方法和destory方法中要用@before和@after修饰
分别表示:@before:在测试之前
@after:在测试之后
2,增加,修改,删除均要提交事务
//提交事务
sqlSession.commit();
示例二:模糊查询
<select id="findUserByName" parameterType="string" resultType="com.model.User"> select * from user where name like #{name}; <!-- prepateStatement的参数占位符 --> <!--注意这里的vale的名称不能改变 字符窜拼接,可能字符串注入 select * from user where name like '%${value}%'; --> </select>
注意:用未带%%的方式,传递参数时要自带%%号
//测试模糊查询 @Test public void testfindUserByName() { List<User> users=userDao.findUserByName("%o%"); for(User user:users) { System.out.println(user); } }
示例三:获取刚插入的id
1 2 <!-- 保存操作 --> 3 <insert id="saveUser" parameterType="com.model.User"> 4 <!-- 配置插入操作后,获取插入数据的id --> 5 <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER"> 6 select last_insert_id(); 7 8 </selectKey> 9 insert into user (name) values(#{name}); 10 </insert>
OGNL表达式
object graphic navigation language(对象 图 导航 语言)
它是通过对象的取值方法来获取数据,在写法上把get省略了。
比如:类中获取:user.getUsername()
OGNL:user.username
mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值未pojo属性名称
pojo:就是一个java bean实体对象
实例:
1 public class QueryVo { 2 private User user; 3 4 public User getUser() { 5 return user; 6 } 7 8 public void setUser(User user) { 9 this.user = user; 10 } 11 }
<!-- 根据queryvo的条件查询用户 --> <select id="fingUserByVo" parameterType="com.model.QueryVo" resultType="com.model.User"> select * from user where name like #{user.name}; </select>
1 //测式使用queryvo 2 @Test 3 public void testfindUserByQueryVo() { 4 QueryVo vo=new QueryVo(); 5 User user=new User(); 6 user.setName("%o%"); 7 vo.setUser(user); 8 List<User> users=userDao.findUserByVo(vo); 9 for(User u:users) { 10 System.out.println(u); 11 } 12 }
1,实体类的属性与数据库表的字段名称不同时:
注意:windows操作系统中的MySQL数据库不区分大小写,Linux系统区分大小写。
即username与userName等价
解决方法:sql语句中使用别名的方法,效率高
配置查询结果集的列名和实体类的属性名的对应关系,更加方便
1 public class TUser { 2 @Override 3 public String toString() { 4 return "TUser [name=" + name + ", id=" +userId + ", pwd=" + pwd + ", userSchool=" + userSchool + "]"; 5 } 6 String name; 7 int userId; 8 9 String pwd; 10 String userSchool; 11 12 public int getUserId() { 13 return userId; 14 } 15 public void setUserId(int userId) { 16 this.userId = userId; 17 } 18 public String getName() { 19 return name; 20 } 21 public void setName(String name) { 22 this.name = name; 23 } 24 25 public String getPwd() { 26 return pwd; 27 } 28 public void setPwd(String pwd) { 29 this.pwd = pwd; 30 } 31 public String getUserSchool() { 32 return userSchool; 33 } 34 public void setUserSchool(String userSchool) { 35 this.userSchool = userSchool; 36 } 37 }
对应的表结构:
id username password school
<!-- 配置查询结果的列名给实体类的属性名的对应关系 --> <resultMap id="userMap" type="com.model.TUser"> <!-- 主键对应的字段 --> <id property="userId" column="id"></id> <!-- 非主键对应的字段 property=java类中的属性名 column=对应表的字段名 --> <result property="name" column="username" ></result> <result property="pwd" column="password" ></result> <result property="userSchool" column="school" ></result> </resultMap> <!-- 查询所有 --> <select id="findTUsersAll" resultMap="userMap"> select * from tb_user; </select>