前期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创建项目,导入依赖
"1.0" encoding="UTF-8"?>"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"> 4.0.0 com.cong mybatis_account_CRUD_annotation 1.0-SNAPSHOT jar org.mybatis mybatis 3.4.5 mysql mysql-connector-java 5.1.6 log4j log4j 1.2.17 junit junit 4.12
2.实体类
package com.cong.pojo; public class Account { 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.配置文件SqlMapConfig.xml
"1.0" encoding="UTF-8"?> DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">"com.cong.pojo"> default="account"> "account"> "JDBC"> "POOLED"> "driver" value="com.mysql.jdbc.Driver"> "url" value="jdbc:mysql://localhost:3306/cong"> "username" value="root"> "password" value="123456"> class="com.cong.mapper.AccountMapper">
4.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
5.mapper接口
package com.cong.mapper; import com.cong.pojo.Account; import org.apache.ibatis.annotations.*; import java.util.List; public interface AccountMapper { @Select("select * from account") ListfindAll(); @Select("select * from account where id = #{id}") Account findById(int id); @Select("select * from account where name like #{name}") //@Select("select * from account where name like '%${value}%'") List findByName(String name); @Select("select count(*) from account") int findTotal(); @Insert("insert into account(name,money) values(#{name},#{money})") //@SelectKey(statement="select last_insert_id()",before=false,keyProperty="id",resultType=Integer.class,keyColumn="id") @Options(useGeneratedKeys=true, keyProperty="id", keyColumn="id")//返回自增字段的id,上面的语句也是一样的效果 int saveAccount(Account account);//返回值是数据库的影响条目,而不是插入的id,想要获取自增的id,只需要在访问一次这个对象即可。 @Delete("delete from account where id = #{id}") void deleteAccount(int id); @Update("update account set name=#{name},money=#{money} where id = #{id}") void updateAccount(Account account); /** * 我们现在操作的是对象Account,如果Account属性比较多, * 我们只是更新Account的单个属性,难道我们再重新生成一个Account传进去? * No,我们可以使用下面这种形式的update * 我们使用@Param参数,只是传递我们感兴趣的参数即可。 * 传入的参数是name,而在@Param中被重新定义成n, * 那么在Sql中就可以通过${n}直接使用了,这个实际上是解决函数参数和Sql参数的阻抗不匹配情况。 */ @Update("update account set name=#{n} where id = #{i}") void updateAccountByParam(@Param("n")String name,@Param("i")int id); }
6.测试类
import com.cong.mapper.AccountMapper; import com.cong.pojo.Account; 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.InputStream; import java.util.List; public class TestCRUD { InputStream inputStream = null; SqlSession sqlSession = null; AccountMapper mapper = null; @Test public void findAll() { Listaccounts = mapper.findAll(); for (Account account : accounts) { System.out.println(account.toString()); } } @Test public void findById() { Account account = mapper.findById(2); System.out.println(account.toString()); } @Test public void findByName() { List accounts = mapper.findByName("%on%");//like #{name}写法 // List accounts = mapper.findByName("on"); //like ‘%${value}%’ 写法 for (Account account : accounts) { System.out.println(account.toString()); } } @Test public void findTotal(){ int accountTotal = mapper.findTotal(); System.out.println("account total:" + accountTotal); } @Test public void save() { Account account = new Account(); account.setName("cong"); account.setMoney(1000f); mapper.saveAccount(account); //在mapper中写了返回自增对象的id,所以这里的对象会包含id属性 System.out.println(account.toString()); } @Test public void update() { Account account = new Account(); account.setName("cong"); account.setMoney(222); account.setId(10); mapper.updateAccount(account); } @Test public void updateByParam() { String name = "Rainbow Cai"; int id = 4; mapper.updateAccountByParam(name,id); } @Test public void deleteAccount() { mapper.deleteAccount(28); } @Before//在测试方法执行之前执行 public void init() throws Exception { //1.读取配置文件,生成字节输入流 inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); //2.获取SqlSessionFactoryBuilder SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); //3.使用工厂生产SqlSession对象 sqlSession = factory.openSession(); //4.使用SqlSession创建mapper接口的代理对象 mapper = sqlSession.getMapper(AccountMapper.class); //5.然后使用代理对象执行mapper接口中的方法 } @After//在测试方法执行之后执行 public void close() throws Exception { //提交事务,增删改需要提交事务,数据库才会发生改变 sqlSession.commit(); //释放资源 sqlSession.close(); inputStream.close(); } }
7.目录结构
这些注解已经能够提供普通SQL语句的替换功能了,如果你的需求比这个还要复杂,那还是使用xml配置为最好。
真正能控制SQL和功能之间的协调关系的还是直接写SQL为宜,将SQL统一管理放置也是通用的做法。
还有一点:Annotation和Xml配置可以同时存在,这个也是必须的。
我们有些Sql特别长且功能比较复杂,写在代码里非常不容易管理,因此提供统一的xml管理还是很有必要的。
注意本文的注解是mybatis本身提供的,和Spring的AOP、IoC特性没有关系,
我们现在做的就是单独使用mybatis来进行开发。至于mybatis和Spring的结合,
其实就是将mybatis的SqlSessionFactory委托为Spring管理,再加上IoC特性,能在使用时节省不少的代码量。
参考:https://isilic.iteye.com/blog/1810782