前言
mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,
使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性;
传统的dao层开发容易出现硬编码的问题。
一、传统DAO层开发:
mybatis传统DAO层开发存在的问题:
1.dao接口中存在大量模版方法,增加工作量。
2.调用sqlSession方法时将statement的id硬编码了
3.调用sqlSession传入的变量,由于sqlSession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序开发。
二、mapper代理开发Mapper接口:
mapper代理开发和传统开发主要的区别在于
1. 接口不用实现
2. mapper文件的namespace有意义,必须与mapper接口类路径一致。
3. Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
4. mapper接口方法名的输入和输出参数必须和mapper.xml中定义的类型一致。
mapper代理方式的mybatis的CRUD个人案例,传送门:https://www.cnblogs.com/ccoonngg/p/11254600.html
其实学习完mapper代理开发之后,可能你还存在一个疑问,就是返回的结果如果是list,代理内部会怎么判断?
- 代理内部会自动判断,如果返回list那么就调用sqlsession的selectlist方法,如果是对象,就调用sqlsession的selectone方法。
总结:mapper代理开发接口不用写实现类,节省了我们的代码量;mapper代理对象减少了我们的硬编码,使编码更加灵活。
---------------------------------------------------------------------------------------------------------------------------------------------------
以下是编写dao层实现类的个人案例
前期mysql准备
create database cong use cong; create table account( id int primary key auto_increment, name varchar(40), money float )character set utf8 collate utf8_general_ci; insert into account(name,money) values('aaa',1000); insert into account(name,money) values('bbb',1000); insert into account(name,money) values('ccc',1000);
1.创建maven工程,导入依赖
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.cong</groupId> <artifactId>mybatis_traditionnal_dao</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <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>5.1.6</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies> </project>
2.创建com.cong.pojo.Account类
package com.cong.pojo; import java.io.Serializable; public class Account implements Serializable{ private int id; private String name; private float money; @Override public String toString() { return "Account{" + "id=" + id + ", name='" + name + '\'' + ", money=" + money + '}'; } 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 float getMoney() { return money; } public void setMoney(float money) { this.money = money; } }
3.创建com.cong.mapper包,创建mapper接口以及实现类
package com.cong.mapper; import com.cong.pojo.Account; import java.util.List; public interface AccountMapper { List<Account> findAll(); Account findById(int id); List<Account> findByName(String name); int findTotal(); void saveAccount(Account account); void updateAccount(Account account); void deleteAccount(int id); } package com.cong.mapper; import com.cong.pojo.Account; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import java.util.List; public class AccountMapperImpl implements AccountMapper { private SqlSessionFactory factory; public AccountMapperImpl(SqlSessionFactory factory) { this.factory = factory; } @Override public List<Account> findAll() { //1.根据factory获取SqlSession对象 SqlSession session = factory.openSession(); //2.调用SqlSession中的方法,实现查询列表 //参数就是能获取配置信息的key,也就是mapper.xml中namespace加上方法名称 List<Account> accounts = session.selectList("accountMapper.findAll"); //3.释放资源 session.close(); return accounts; } @Override public Account findById(int id) { //1.根据factory获取SqlSession对象 SqlSession session = factory.openSession(); //2.调用SqlSession中的方法,实现按照id查询 //参数就是能获取配置信息的key Account account = session.selectOne("accountMapper.findById",id); //3.释放资源 session.close(); return account; } @Override public List<Account> findByName(String name) { //1.根据factory获取SqlSession对象 SqlSession session = factory.openSession(); //2.调用SqlSession中的方法,实现按照名字模糊查询列表 List<Account> accounts = session.selectList("accountMapper.findByName",name); //3.释放资源 session.close(); return accounts; } @Override public int findTotal() { //1.根据factory获取SqlSession对象 SqlSession session = factory.openSession(); //2.调用SqlSession中的方法,实现查询数量 int total = session.selectOne("accountMapper.findTotal"); //3.释放资源 session.close(); return total; } @Override public void saveAccount(Account account) { //1.根据factory获取SqlSession对象 SqlSession session = factory.openSession(); //2.调用SqlSession中的方法,实现保存 session.insert("accountMapper.saveAccount",account); //提交 session.commit(); //3.释放资源 session.close(); } @Override public void updateAccount(Account account) { //1.根据factory获取SqlSession对象 SqlSession session = factory.openSession(); //2.调用SqlSession中的方法,实现更新 session.update("accountMapper.updateAccount",account); //提交 session.commit(); //3.释放资源 session.close(); } @Override public void deleteAccount(int id) { //1.根据factory获取SqlSession对象 SqlSession session = factory.openSession(); //2.调用SqlSession中的方法,实现删除 session.delete("accountMapper.deleteAccount",id); //提交 session.commit(); //3.释放资源 session.close(); } }
4.在resources下创建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> <typeAliases> <typeAlias type="com.cong.pojo.Account" alias="account"></typeAlias> </typeAliases> <environments default="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/cong"></property> <property name="username" value="root"></property> <property name="password" value="123456"></property> </dataSource> </environment> </environments> <mappers> <mapper resource="com/cong/mapper/AccountMapper.xml"></mapper> </mappers> </configuration>
5.在resources创建log4j.properties配置文件
# Set root category priority to INFO and its only appender to CONSOLE. #log4j.rootCategory=INFO, CONSOLE debug info warn error fatal log4j.rootCategory=debug, CONSOLE, LOGFILE # Set the enterprise logger category to FATAL and its only appender to CONSOLE. log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE # CONSOLE is set to be a ConsoleAppender using a PatternLayout. log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n # LOGFILE is set to be a File appender using a PatternLayout. log4j.appender.LOGFILE=org.apache.log4j.FileAppender log4j.appender.LOGFILE.File=d:\axis.log log4j.appender.LOGFILE.Append=true log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
6.在resources下创建目录com/cong/mapper,然后创建AccountMapper.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"> <!-- 此处namespace没有特殊意义 --> <mapper namespace="accountMapper"> <!-- 查询所有 --> <select id="findAll" resultType="account"> select * from account; </select> <!-- 根据id查询用户 --> <select id="findById" parameterType="INT" resultType="account"> select * from account where id = #{uid} </select> <!-- 根据名称模糊查询 --> <select id="findByName" parameterType="string" resultType="account"> select * from account where name like #{name} </select> <!-- 获取用户的总记录条数 --> <select id="findTotal" resultType="int"> select count(id) from account; </select> <!-- 保存用户 --> <insert id="saveAccount" parameterType="account"> <selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER"> select LAST_INSERT_ID(); </selectKey> <!-- 配置插入操作后,获取插入数据的id --> insert into account(name,money) values(#{name},#{money}) </insert> <!-- 更新用户 --> <update id="updateAccount" parameterType="account"> update account set name=#{name},money=#{money} where id=#{id} </update> <!-- 删除用户--> <delete id="deleteAccount" parameterType="java.lang.Integer"> delete from account where id = #{uid} </delete> </mapper>
7.创建测试类
import com.cong.mapper.AccountMapper; import com.cong.mapper.AccountMapperImpl; import com.cong.pojo.Account; import org.apache.ibatis.io.Resources; 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.InputStream; import java.util.List; public class TestAccount { public InputStream inputStream; public AccountMapper mapper; @Test public void findAll(){ List<Account> accounts = mapper.findAll(); for (Account account : accounts) { System.out.println(account.toString()); } } @Test public void findById(){ Account account = mapper.findById(1); System.out.println(account.toString()); } @Test public void findByName(){ List<Account> accounts = mapper.findByName("%ong%"); for (Account account : accounts) { System.out.println(account.toString()); } } @Test public void findTotal(){ int accounts = mapper.findTotal(); System.out.println(accounts); } @Test public void saveAccount(){ Account account = new Account(); account.setName("rainbow"); account.setMoney(222222); mapper.saveAccount(account); System.out.println(account); } @Test public void updateAccount(){ Account account = new Account(); account.setName("rainbow"); account.setMoney(222222); account.setId(6); mapper.updateAccount(account); } @Test public void deleteAccount(){ mapper.deleteAccount(8); } @Before public void init() throws Exception{ //1.读取配置文件,生成字节输入流 inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); //2.获取SqlSessionFactory SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); //3.使用工厂对象,创建mapper对象 mapper = new AccountMapperImpl(factory); } @After public void destroy() throws Exception{ inputStream.close(); } }
8.完整目录结构
下面是编写dao层实现类Mybatis的执行过程,例子与我的案例不同,不过还是可以看懂的
参考:https://blog.csdn.net/changyinling520/article/details/78102734