MyBatis总结
一、MyBatis简介
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层1框架。 iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
当前,最新版本是MyBatis 3.5.5 ,其发布时间是2020年6月4日
1、基本信息
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
2、特点
- 简单易学: 本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活: mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- 解除sql与程序代码的耦合: 通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql。
二、MyBatis开端
- 什么是mybatis?
MyBatis 是一款基于java的持久层框架 - 持久化: 数据从瞬间状态变为持久状态。
- 持久层: 完成持久化工作的代码块。—dao
- Mybatis就是帮助程序猿将数据存入数据库中,和从数据库中取数据。
- 传统的jdbc操作: 有很多重复代码块。比如:数据取出时的封装。数据库的建立连接等等。通过框架可以减少重复代码,提高开发效率。
- Mybatis是一个半自动化的ORM框架。O—object,R—relationship,M—mapping
- Mybatis的功能:
Mybatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。Mybatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。
因为本猿比较懒,所以使用的是idea编程,那些编程软件导入jar包的步骤太繁琐了,我放弃了。
三、开发第一个应用
准备工作:
相关jar包展示,用其他软件的自己去网上搜去!idea不用特地导入jar包
1、引入pom.xml依赖:
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!-- log4j -->
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.27.0-GA</version>
</dependency>
2、编写mybatis核心配置文件
a、点击file—Settings—Editor—file and code Templates
第六个步骤改一下,改成下面这个,比较方便:
这个也是配置解析:
<?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="development">
<!--连接环境信息,取一个任意唯一的名字-->
<environment id="development">
<!--mybatis使用jdbc事务管理方式
JDBC-这个配置直接使用JDBC的提交和回滚功能。它依赖于从数据源获得连接来管理事务的生命周期。
MANAGED-这个配置基本上什么都不做。它从不提交或者回滚一个连接的事务。而是让容器(例如:Spring或者J2EE应用服务器)来管理事务的生命周期
-->
<transactionManager type="JDBC"/>
<!--
数据源类型:
UNPOOLED-这个类型的数据源实现只是在每次需要的时候简单地打开和关闭连接。
POOLED-这个数据源的实现缓存了JDBC连接对象,用于避免每次创建新的数据库连接
时都初始化和进行认证,加快程序响应。并发WEB应用通常这种做法来获得快速响应。
-->
<!--mybatis使用连接池方式来获取连接-->
<dataSource type="POOLED">
<!--配置与数据库交互的4个必要属性-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/> <!--value填数据库的名字-->
<property name="password" value="123455"/> <!--value填自己数据库的密码-->
</dataSource>
</environment>
</environments>
<!--配置映射文件的位置-->
<mappers>
<mapper resource="cn/sxt/entity/user.mapper.xml"/>
</mappers>
</configuration>
b、配置mybatis-config.xml的网址,点击file–Settings–ages& Frameworks–Schmas and DTDs
c、在target创建mybatis-config文件
我的MySQL表名称和内容:
3、创建SqlSessionFactory,以及获得SqlSession
MyBatisUtil.java
package Mybatis.mybatis01_hello.util;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.io.Resources;
import java.io.InputStream;
//创建SqlSessionFactory,以及获得SqlSession
public class MyBatisUtil {
/**
* 通过配置文件 创建SqlSessionFactory 是一个SqlSession的工厂类
*/
public static SqlSessionFactory getSqlSessionFactory() throws Exception {
//得到配置文件流
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
return sqlSessionFactory;
}
/**
* SqlSession 通过id 找到对应的sql语句,执行sql语句
*/
public static SqlSession getSession() throws Exception {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
return sqlSessionFactory.openSession();
}
}
4、创建实体类
User.java
package Mybatis.mybatis01_hello.entity;
public class User {
private int id;
private String name;
private String pwd;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
5、编写sql语句的映射文件----添加到核心文件配置中
user.mapper.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="cn.sxt.entity.UserMapper">
<select id="selectUser" resultType="Mybatis.mybatis01_hello.entity.User"> <!--resultType输入包名+类名-->
select * from user where id = #{id}
</select>
</mapper>
6、编写测试类
Test.java
package Mybatis.mybatis01_hello.test;
import Mybatis.mybatis01_hello.entity.User;
import Mybatis.mybatis01_hello.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
public class Test {
public static void main(String[] args) throws Exception {
SqlSession session = MyBatisUtil.getSession();
User user = session.selectOne("Mybatis.mybatis01_hello.entity.UserMapper.selectUser", 1);
System.out.println("id= " + user.getId() + "name= " + user.getName() + "pwd= " + user.getPwd());
session.close();
}
}
四、基本的crud操作
-
搭建mybatis框架
a、导入相关jar包
b、编写核心配置文件(配置数据库连接的相关信息以及配置了mapper映射文件)
c、编写dao文件操作
d、编写mapper映射文件
e、编写实体类 -
实现crud
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.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/test"></property> <property name="username" value="root"></property> <property name="password" value="yxd1514"></property> </dataSource> </environment> </environments> <!--配置映射文件的位置--> <mappers> <mapper resource="dao/IUserDao.xml"></mapper> </mappers> </configuration>
UserMapper.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="dao.IUserDao"> <!--查询所有--> <select id="findAll" resultType="domain.User"> select * from user; </select> <!--保存用户--> <insert id="saveUser" parameterType="domain.User"> <!--配置插入操作后,获取数据的id--> <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER"> select last_insert_id(); </selectKey> insert into user(id, name, pwd)values(#{id},#{name},#{pwd}); </insert> <!--更新用户--> <update id="updateUser" parameterType="domain.User"> update user set name=#{name}, pwd=#{pwd} where id=#{id}; </update> <!--删除用户--> <delete id="deleteUser" parameterType="java.lang.Integer"> delete from user where id=#{uid} </delete> <!--根据id查询用户--> <select id="findById" parameterType="int" resultType="domain.User"> select * from user where id=#{uid} </select> <!--根据名字模糊查询--> <select id="findByName" parameterType="string" resultType="domain.User"> <!--select * from user where name like #{name}--> select * from user where name like '%${value}%' </select> <!--获取用户的总记录条数--> <select id="findTotal" resultType="int"> select count(id) from user; </select> <!--根据queryVo的条件查询用户--> <select id="findUserByVo" parameterType="domain.QueryVo" resultType="domain.User"> select * from user where name like #{user.name} </select> </mapper>
User.java
package domain; import java.io.Serializable; public class User implements Serializable { private int id; private String name; private String pwd; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } }
UserDao.java
package dao; import domain.QueryVo; import domain.User; import java.util.List; import java.util.Queue; /** * 用户的持久层接口 */ public interface IUserDao { /** * 查询所有用户 */ List<User> findAll(); /** * 保存用户 * @param user */ void saveUser(User user); /** * 更新用户 * @param user */ void updateUser(User user); /** * 根据id删除用户 */ void deleteUser(Integer id); /** * 根据id查询用户信息 */ User findById(Integer id); /** * 根据名称模糊查询用户信息 */ List<User> findByName(String name); /** * 查询总用户数 */ int findTotal(); /** * 根据queryVo中的条件查询用户 * @param vo * @return */ List<User> findUserByVo(QueryVo vo); }
QueryVo.java
package domain; public class QueryVo { private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
调用dao进行操作
package test; import dao.IUserDao; import domain.QueryVo; import domain.User; 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.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; /** * 测试mybatis的crud操作 */ public class MybatisTest { private InputStream in; private SqlSession sqlSession; private IUserDao userDao; @Before//用于在测试方法执行之前执行 public void init() throws IOException { //1.读取配置文件,生成字节输入流 in = Resources.getResourceAsStream("SqlMapConfig.xml"); //2.获取SQLSessionFactory SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //3.获取SQLSession对象 sqlSession = factory.openSession(); //4.获取dao的代理对象 userDao = sqlSession.getMapper(IUserDao.class); } @After//用于在测试方法之后执行 public void destroy() throws Exception { //提交事务 sqlSession.commit(); //6.释放资源 sqlSession.close(); in.close(); } /** * 测试查询所有 */ @Test public void testFindAll() { //5.查询所有方法 List<User> users = userDao.findAll(); for (User user : users){ System.out.println(user); } } /** * 测试保存操作 */ @Test public void testSave() { User user = new User(); user.setId(11); user.setName("韩信"); user.setPwd("1122"); System.out.println("保存操作之前:" + user); //5.执行保存方法 userDao.saveUser(user); System.out.println("保存操作之后:" + user); } /** * 测试更新(修改)操作 */ @Test public void testUpdate() { User user = new User(); user.setId(1); user.setName("李香"); user.setPwd("1112"); //5.执行修改方法 userDao.updateUser(user); } /** * 测试删除操作 */ @Test public void testDelete() { //5.执行删除方法 userDao.deleteUser(11); } /** * 测试查询一个操作 */ @Test public void testFindOne() { //5.执行查询一个方法 User user = userDao.findById(2); System.out.println(user); } /** * 测试模糊查询操作 */ @Test public void testFindByName() { //5.执行模糊查询方法 // List<User> users = userDao.findByName("%信%"); d List<User> users = userDao.findByName("信"); for (User user: users){ System.out.println(user); } } /** * 测试查询总记录条数 */ @Test public void testFindTotal() { //5.执行查询总记录条数 int count = userDao.findTotal(); System.out.println(count); } /** * 测试使用QueryVo作为查询条件 */ @Test public void testFindByVo() { QueryVo vo = new QueryVo(); User user = new User(); user.setName("香"); vo.setUser(user); //5.执行使用QueryVo作为查询条件 List<User> users = userDao.findUserByVo(vo); for (User u: users){ System.out.println(u); } } }
五、配置优化
导入properties配置文件
-
在src下创建db.properties配置文件
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/test username=root password=1214
-
在mybatis-config.xml中做如下修改:
<properties resource="db.properties"/> <!--配置与数据库交互的4个必要属性--> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/>
1、别名的优化:
mybatis-config.xml添加下列语句:
<typeAliases>
<!--为指定类型指名 别名 使得在mapper映射文件中可以简化引用-->
<typeAlias type="cn.sxt.entity.User" alias="User"/>
<!--为某个包下的所有类指定别名 默认别名是对应的类名-->
<!--<package name="cn.sxt.entity.User"/>-->
</typeAliases>
把user-mapper.xml里的cn.sxt.entity.User替换成User,运行Test,结果一样。
2、解决属性名与列名不一致
User.java
public class User {
private int id;
private String name;
//private String pwd;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
// public String getPwd() {
// return pwd;
// }
//
// public void setPwd(String pwd) {
// this.pwd = pwd;
// }
// @Override
// public String toString() {
// return "User{" +
// "id=" + id +
// ", name='" + name + '\'' +
// ", pwd='" + pwd + '\'' +
// '}';
// }
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
把pwd改为password后,运行时password输出会出现null:
问题: 密码没有获取到
原因: mybatis会根据查询的列名(会将列名转为小写)去进行设值(列名setter方法)
解决列名和属性名不一致的两种方法:
a、为列名指定别名和java实体类的属性名一致
user.mapper.xml
<!-- 查询所有用户 -->
<select id="selectAll" resultType="User">
select id,name,pwd password from user
</select>
b、设置结果映射类型
<!-- 查询单个用户
id在该文件中是唯一-->
<select id="selectUser" resultType="UserMap">
select id,name,pwd password from user where id = #{id}
</select>
<!-- id为主键 -->
<resultMap id="UserMap" type="User">
<!--column是数据库中表的列名 property是对应实体类的属性名-->
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
六、分页的实现
1. 分析mysql的分页语句:limit startIndex,pageNum
user.mapper.xml映射文件
<!-- 查询所有用户 -->
<select id="selectAll" parameterType="Map" resultType="User">
select * from user limit #{startIndex},#{pageSize}
</select>
UserDao.java:
//分页查询
public List<User> getAll(int currentPage,int pageSize) throws IOException {
SqlSession session = MyBatisUtil.getSession();
Map<String,Integer> map = new HashMap<String, Integer>();
map.put("startIndex",(currentPage-1)*pageSize);
map.put("pageSize",pageSize);
List<User> list = session.selectList("cn.sxt.entity.UserMapper.selectAll",map);
return list;
}
注意: 不用为参数设置类,可以采用map结构来解决这个问题。
2. 通过RowBounds来实现分页
user.mapper.xml
<select id="getAll" resultType="User">
select * from user
</select>
UserDao.java中新建RowBounds对象
RowBounds rowBounds = new RowBounds(index,size); index是下标,size数据
UserDao.java
public List<User> getAll(int currentPage,int pageSize) throws IOException {
SqlSession session = MyBatisUtil.getSession();
RowBounds rowBounds = new RowBounds((currentPage-1)*pageSize,pageSize);
List<User> list = session.selectList("cn.sxt.entity.UserMapper.getAll",null,rowBounds);
session.close();
return list;
}
Tset.java
package Mybatis.mybatis01_hello.test;
import Mybatis.mybatis01_hello.entity.User;
import org.apache.ibatis.session.SqlSession;
public class Test {
public static void main(String[] args) throws Exception {
UserDao userDao = new UserDao();
List<User> list = userDao.getAll(1,3);
for (User u:list) {
System.out.println(u);
}
}
}
结果为:
七、使用注解实现mybatis
-
面向接口编程:
好处: 扩展性好,分层开发中,上层不用管具体的实现,大家都遵循共同的标准,使得开发变得容易。规范性更好 -
注解的实现
IUserDao.javapackage dao; import mybatis_test.User; import org.apache.ibatis.annotations.Select; import java.util.List; /** * 用户持久层接口 */ public interface IUserDao { /** * 查询所有操作 * @return */ @Select("select * from user") List<User> findAll(); }
mapconfig.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"> <!--MyBatis的主配置文件--> <configuration> <!--设置一个默认的连接环境信息--> <environments default="development"> <!--配置Mysql的环境--> <environment id="development"> <!--mybatis使用jdbc事务管理方式 JDBC-这个配置直接使用JDBC的提交和回滚功能。它依赖于从数据源获得连接来管理事务的生命周期。 MANAGED-这个配置基本上什么都不做。它从不提交或者回滚一个连接的事务。而是让容器(例如:Spring或者J2EE应用服务器)来管理事务的生命周期 --> <transactionManager type="JDBC"/> <!-- 数据源类型: UNPOOLED-这个类型的数据源实现只是在每次需要的时候简单地打开和关闭连接。 POOLED-这个数据源的实现缓存了JDBC连接对象,用于避免每次创建新的数据库连接 时都初始化和进行认证,加快程序响应。并发WEB应用通常这种做法来获得快速响应。 --> <!--mybatis使用连接池方式来获取连接(配置数据源)--> <dataSource type="POOLED"> <!--配置与数据库交互的4个必要属性--> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test"/> <property name="username" value="root"/> <property name="password" value="yxd1514"/> </dataSource> </environment> </environments> <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限定类名 --> <mappers> <mapper class="dao.IUserDao"/> </mappers> </configuration>
User.java
package mybatis_test; import java.io.Serializable; public class User implements Serializable { private int id; private String name; private String pwd; public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd=" + pwd + '}'; } }
Test.java
package test;
import dao.IUserDao;
import mybatis_test.User;
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 java.io.InputStream;
import java.util.List;
/**
* mybatis入门案例
*/
public class MybatisTest {
/**
* 入门案例
* @param args
*/
public static void main(String[] args) throws Exception {
//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();
}
}
运行Test,得如下结果:
与前面的方法相比,这个方法简便很多。
八、关于联表的处理
多对一的处理
-
数据库表的设计
新创建两个表student和teacher
-
实体类
Teacher.javapackage cn.sxt.entity; public class Teacher { private int id; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } }
Student.java
package cn.sxt.entity; public class Student { private int id; private String name; private Teacher teacher; //多个学生对应一个老师 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Teacher getTeacher() { return teacher; } public void setTeacher(Teacher teacher) { this.teacher = teacher; } }
mapconfig.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"> <!--MyBatis的主配置文件--> <configuration> <!--设置一个默认的连接环境信息--> <environments default="development"> <!--配置Mysql的环境--> <environment id="development"> <!--mybatis使用jdbc事务管理方式 JDBC-这个配置直接使用JDBC的提交和回滚功能。它依赖于从数据源获得连接来管理事务的生命周期。 MANAGED-这个配置基本上什么都不做。它从不提交或者回滚一个连接的事务。而是让容器(例如:Spring或者J2EE应用服务器)来管理事务的生命周期 --> <transactionManager type="JDBC"/> <!-- 数据源类型: UNPOOLED-这个类型的数据源实现只是在每次需要的时候简单地打开和关闭连接。 POOLED-这个数据源的实现缓存了JDBC连接对象,用于避免每次创建新的数据库连接 时都初始化和进行认证,加快程序响应。并发WEB应用通常这种做法来获得快速响应。 --> <!--mybatis使用连接池方式来获取连接(配置数据源)--> <dataSource type="POOLED"> <!--配置与数据库交互的4个必要属性--> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test"/> <property name="username" value="root"/> <property name="password" value="yxd1514"/> </dataSource> </environment> </environments> <mappers> <mapper resource="tudent.mapper.xml"/> </mappers> </configuration>
-
编写映射文件student.mapper.xml
<mapper namespace=cn.sxt.entity.student.mapper"> <!-- 多对一处理有两种方式 1、按结果嵌套处理 2、按查询嵌套处理 --> <!--按结果嵌套处理--> <select id="getStudents" resultMap="StudentTeacher"> select s.id sid,s.name sname,s.tid stid,t.id tid,t.name tname from student s,teacher t where s.tid=t.id </select> <resultMap id="StudentTeacher" type="cn.sxt.entity.Student"> <id column="sid" property="id"/> <result column="sname" property="name"/> <!--关联对象 property 关联对象在Student 实体类中的属性--> <association property="teacher" javaType="cn.sxt.entity.Teacher"> <id column="tid" property="id"/> <result column="tname" property="name"/> </association> </resultMap> </mapper>
-
编写映射文件student.mapper.xml:
两种方式:
a.按结果嵌套处理
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="tool.student.mapper">
<!--
多对一处理有两种方式
1、按结果嵌套处理
2、按查询嵌套处理
-->
<!--按结果嵌套处理-->
<select id="getStudents" resultMap="StudentTeacher">
select s.id sid,s.name sname,s.tid stid,t.id tid,t.name tname from student s,teacher t where s.tid=t.id
</select>
<resultMap id="StudentTeacher" type="cn.sxt.entity.Student">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
<!--关联对象 property 关联对象在Student 实体类中的属性-->
<association property="teacher" javaType="cn.sxt.entity.Teacher">
<id column="tid" property="id"/>
<result column="tname" property="name"/>
</association>
</resultMap>
</mapper>
b.查询嵌套处理
<!--
按查询嵌套处理
-->
<select id="getStudents" resultMap="StudentTeacher">
select * from student
</select>
<resultMap id="StudentTeacher" type="cn.sxt.entity.Student">
<!--association关联属性 property属性名 javaType属性的类型 column关联属性在多的一方表中的列名-->
<association property="teacher" column="tid" javaType="cn.sxt.entity.Teacher" select="getTeacher">
</association>
</resultMap>
<select id="getTeacher" resultType="cn.sxt.entity.Teacher">
select * from teacher where id=#{id}
</select>
一对多的处理
数据库与上面的相同
- 实体类:
Student.java
package cn.sxt.entity;
public class Student {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Teacher.java
package cn.sxt.entity;
import java.util.List;
public class Teacher {
private int id;
private String name;
private List<Student> students;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
- 编写映射文件teacher.mapper.xml:
两种处理方式:
第一种:
teacher.mapper.xml
<mapper namespace="cn.sxt.entity.teacher.mapper">
<select id="getTeacher" resultMap="TeacherStudent">
select s.id sid,s.name sname,s.tid stid,t.id tid,t.name tname from student s,teacher t where s.tid=t.id
</select>
<resultMap id="TeacherStudent" type="cn.sxt.entity.Teacher">
<id column="tid" property="id"/>
<result column="tname" property="name"/>
<collection property="students" ofType="cn.sxt.entity.Student">
<id column="sid" property="id"/>
<result column="sname" property="name"/>
</collection>
</resultMap>
</mapper>
TeacherDao.java
public class TeacherDao {
public Teacher getTeacher(int id) throws IOException{
SqlSession session = MyBatisUtil.getSession();
Teacher teacher = session.selectOne("cn.sxt.entity.teacher.mapper.getTeacher",id);
session.close();
return teacher;
}
}
mybatis.config.xml
<mappers>
<mapper resource="cn/sxt/entity/student.mapper.xml"/>
</mappers>
Test.java
public class Test {
public static void main(String[] args) throws IOException {
TeacherDao teacherDao = new TeacherDao();
Teacher teacher = teacherDao.getTeacher(1);
System.out.println("teacher name=" + teacher.getName());
List<Student> list = teacher.getStudents();
for (Student stu:list){
System.out.println("Student name=" + stu.getName());
}
第二种:
teacher.mapper.xml
<select id="getTeacher" resultMap="TeacherStudent">
select * from teacher where id=#{id}
</select>
<resultMap id="TeacherStudent" type="cn.sxt.entity.Teacher">
<!--column是一端在多端的外键,写的是一端的主键列名-->
<collection property="students" javaType="ArrayList" ofType="cn.sxt.entity.Student" column="id" select="cn.sxt.entity.Student.mapper.gteStudentByTid"></collection>
</resultMap>
student.mapper.xml
<select id="getStudentByTid" resultType="cn.sxt.entity.Student">
select * form student where tid=#{id}
</select>
mybatis.config.xml
<mappers>
<mapper resource="cn/sxt/entity/student.mapper.xml"/>
<mapper resource="cn/sxt/entity/teacher.mapper.xml"/>
</mappers>
九、动态sql
MyBatis最强大的特性之一就是它的动态语句功能。 如果您以前有使用JDBC或者类似框架的经历,您就会明白把SQL语句条 件连接在一起是多 么的痛苦,要确保不能忘记空格或者不要在columns列后面省略一个逗号等。动态语句能够完全解决掉这些痛苦。
尽管与动态SQL-起工作不是在开- -个party, 但是MyBatis 确实能通过在任何映射SQL语中使用强大的动态SQL来改进这些状况。
动态SQL元素对于任何使用过JSIL或者类似于XML之类的文本处理器的人来说,都是非常熟悉的。在上- -版本中,需要了解和学习非常多的元素,但在MyBatis 3中有了许多的改进,现在只剩下差不多二分之一的元素。 MyBatis 使用了基于强大的OGNL表达式来消除了大部分元素。
●if
●choose (when, otherwise)
●trim (where,set)
●foreach
我们主要了解一下if
1、动态sql指根据不同的查询条件,生成不同的sql语句。
2、Mapper文件
<select id="getUserByCondition" parameterType="Map" resultType="cn.sxt.entity.User">
select * from user
<where>
<if test="name!=null">
name like CONCAT('%',#{name},'%')
</if>
</where>
</select>
上述的是模糊查询
持久化: 数据从瞬时状态变为持久状态
持久层: 完成持久化工作的代码块 ----dao(数据访问对象 Date Access Object) ↩︎