Mybatis 系列4-CRUD
mybatis基于xml和注解的增删改查
首先说下目录结构:
XML配置文件方式:
Mapper接口开发只需编写Mapper接口(Dao接口),mybatis框架会根据接口定义创建接口的代理对象。
本文介绍XML配置方式:
步骤:
1、创建maven工程,导入坐标:
1 <packaging>jar</packaging> 2 <dependencies> 3 <dependency> 4 <groupId>org.mybatis</groupId> 5 <artifactId>mybatis</artifactId> 6 <version>3.5.3</version> 7 </dependency> 8 <dependency> 9 <groupId>mysql</groupId> 10 <artifactId>mysql-connector-java</artifactId> 11 <version>5.1.6</version> 12 </dependency> 13 <dependency> 14 <groupId>log4j</groupId> 15 <artifactId>log4j</artifactId> 16 <version>1.2.17</version> 17 </dependency> 18 <dependency> 19 <groupId>junit</groupId> 20 <artifactId>junit</artifactId> 21 <version>4.12</version> 22 </dependency> 23 </dependencies>
2、编写实体类User.java和持久层接口IUserDao.java
User.java:
1 package com.mantishell.domain; 2 3 import java.io.Serializable; 4 import java.util.Date; 5 6 public class User implements Serializable { 7 8 private Integer id; 9 private String name; 10 private String address; 11 private String sex; 12 private Date birthday; 13 14 public User() { 15 } 16 17 public User(Integer id, String name, String address, String sex, Date birthday) { 18 this.id = id; 19 this.name = name; 20 this.address = address; 21 this.sex = sex; 22 this.birthday = birthday; 23 } 24 25 public Integer getId() { 26 return id; 27 } 28 29 public void setId(Integer id) { 30 this.id = id; 31 } 32 33 public String getName() { 34 return name; 35 } 36 37 public void setName(String name) { 38 this.name = name; 39 } 40 41 public String getAddress() { 42 return address; 43 } 44 45 public void setAddress(String address) { 46 this.address = address; 47 } 48 49 public String getSex() { 50 return sex; 51 } 52 53 public void setSex(String sex) { 54 this.sex = sex; 55 } 56 57 public Date getBirthday() { 58 return birthday; 59 } 60 61 public void setBirthday(Date birthday) { 62 this.birthday = birthday; 63 } 64 65 @Override 66 public String toString() { 67 return "User{" + 68 "id=" + id + 69 ", name='" + name + '\'' + 70 ", address='" + address + '\'' + 71 ", sex='" + sex + '\'' + 72 ", birthday=" + birthday + 73 '}'; 74 } 75 }
QueryVo.java
1 package com.mantishell.domain; 2 3 public class QueryVo { 4 private User user; 5 6 public User getUser() { 7 return user; 8 } 9 10 public void setUser(User user) { 11 this.user = user; 12 } 13 }
IUserDao.java
1 package com.mantishell.dao; 2 3 import com.mantishell.domain.QueryVo; 4 import com.mantishell.domain.User; 5 6 import java.util.List; 7 8 public interface IUserDao { 9 10 List<User> findAll(); 11 12 void saveUser(User user); 13 14 void updateUser(User user); 15 16 void deleteUser(Integer id); 17 18 User findById(Integer userId); 19 20 List<User> findByName(String name); 21 22 //查询总记录数 23 int findTotal(); 24 25 List<User> findUserByVo(QueryVo vo); 26 }
3、配置文件
a、在resources文件夹下,创建主配置文件SqlMapConfig.xml。
b、在resources文件夹下导入log4j.properties文件。
c、在resources文件夹下创建文件夹com->mantishell->dao,创建映射配置文件IUserDao.xml。
在mybatis中,持久层的接口也叫Mapper。所以IUserDao和IUserMapper是一样的。
注意事项:1、映射配置文件必须和持久层接口子相同的包中,且必须以持久层接口名称命名配置文件名+.xml。
2、配置文件中的namespace必须是持久层接口的全限定类名。
3、创建配置文件时特别需要注意:com.mantishell.dao是三级目录
4、映射配置文件的操作配置(select,update),id属性的取值必须是dao接口的方法名
5、只要遵循以上2、3、4三点,就无需写dao的实现类,由mybatis实现(动态代理dao实现)
SqlMapConfig.xml(主配置文件):
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 <!--配置环境,default的名称可以随便填写,填写后environment里必须要有该defaullt的内容--> 7 <environments default="mysql"> 8 <!--配置mysql的环境--> 9 <environment id="mysql"> 10 <!--配置事务的类型--> 11 <transactionManager type="JDBC"></transactionManager> 12 <!--配置数据源(连接池)--> 13 <dataSource type="POOLED"> 14 <property name="driver" value="com.mysql.jdbc.Driver"/> 15 <property name="url" value="jdbc:mysql://localhost:3306/db2?useUnicode=true&characterEncoding=utf8"/> 16 <property name="username" value="root"/> 17 <property name="password" value="123456"/> 18 </dataSource> 19 </environment> 20 </environments> 21 22 <!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 23 如果是注解,此处应使用class属性指定被注解的dao全限定类名 24 --> 25 <mappers> 26 <!-- <mapper resource="com/mantishell/dao/IUserDao.xml" />--> 27 <package name="com.mantishell.dao"/> 28 </mappers> 29 </configuration>
log4j.properties:
1 # Set root category priority to INFO and its only appender to CONSOLE. 2 #log4j.rootCategory=INFO, CONSOLE debug info warn error fatal 3 log4j.rootCategory=debug, CONSOLE, LOGFILE 4 5 # Set the enterprise logger category to FATAL and its only appender to CONSOLE. 6 log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE 7 8 # CONSOLE is set to be a ConsoleAppender using a PatternLayout. 9 log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender 10 log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout 11 log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n 12 13 # LOGFILE is set to be a File appender using a PatternLayout. 14 log4j.appender.LOGFILE=org.apache.log4j.FileAppender 15 log4j.appender.LOGFILE.File=e:/axis.log 16 log4j.appender.LOGFILE.Append=true 17 log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout 18 log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
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 <!--namespace:dao的全限定类名--> 6 <mapper namespace="com.mantishell.dao.IUserDao"> 7 8 <!--配置查询结果的列名和实体类的属性名的对应关系(如果数据库中的字段和pojo中的相同,则这里完全不需要写) 9 然后将下面的resultType全部换成resultMap="userMap" 10 --> 11 <!-- 12 id:唯一标志,随便写 13 type:表示查询的实体类 14 --> 15 <resultMap id="userMap" type="com.mantishell.domain.User"> 16 <!--主键字段的对应--> 17 <id property="id" column="id" /> 18 19 <result property="name" column="name" /> 20 <result property="address" column="address"/> 21 <result property="sex" column="sex"/> 22 <result property="birthday" column="birthday"/> 23 </resultMap> 24 <!--相当于:resultType="com.mantishell.domain.User"--> 25 <select id="findAll" resultMap="userMap"> 26 select * from user; 27 </select> 28 29 <insert id="saveUser" parameterType="com.mantishell.domain.User"> 30 <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER"> 31 select last_insert_id(); 32 </selectKey> 33 insert into user(name,address,sex) values(#{name},#{address},#{sex}); 34 </insert> 35 36 <update id="updateUser" parameterType="com.mantishell.domain.User"> 37 update user set name=#{name},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id} 38 </update> 39 40 <!--这里个占位符uid可以换成任意的--> 41 <delete id="deleteUser" parameterType="Integer"> 42 delete from user where id=#{uid} 43 </delete> 44 45 <select id="findById" parameterType="int" resultType="com.mantishell.domain.User"> 46 select * from user where id=#{userid} 47 </select> 48 49 <!--模糊查询--> 50 <select id="findByName" parameterType="String" resultType="com.mantishell.domain.User"> 51 select * from user where name like #{user} 52 <!--select * from user where name like '%${value}%' 这里的${value}是固定的--> 53 </select> 54 55 <select id="findTotal" resultType="int"> 56 select count(id) from user; 57 </select> 58 59 <!--根据实体类对象查询--> 60 <select id="findUserByVo" parameterType="com.mantishell.domain.QueryVo" resultType="com.mantishell.domain.User"> 61 select * from user where name like #{user.name} 62 </select> 63 </mapper>
4、测试
1 package com.mantishell.test; 2 3 import com.mantishell.dao.IUserDao; 4 import com.mantishell.domain.QueryVo; 5 import com.mantishell.domain.User; 6 import org.apache.ibatis.io.Resources; 7 import org.apache.ibatis.session.SqlSession; 8 import org.apache.ibatis.session.SqlSessionFactory; 9 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 10 import org.junit.After; 11 import org.junit.Before; 12 import org.junit.Test; 13 14 import java.io.InputStream; 15 import java.util.Date; 16 import java.util.List; 17 18 public class MybatisTest { 19 20 private InputStream in; 21 private SqlSession sqlSession; 22 private IUserDao userDao; 23 24 @Before 25 public void init() throws Exception{ 26 //1、读取配置 27 in = Resources.getResourceAsStream("SqlMapConfig.xml"); 28 //2、创建SqlSessionFactory工厂 29 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); 30 //3、使用工厂生产SqlSession对象 31 sqlSession = factory.openSession(); 32 //4、使用SqlSession创建Dao接口的代理对象 33 userDao = sqlSession.getMapper(IUserDao.class); 34 } 35 @After 36 public void destroy() throws Exception{ 37 sqlSession.commit(); 38 sqlSession.close(); 39 in.close(); 40 } 41 42 @Test 43 public void testFindAll() { 44 List<User> users = userDao.findAll(); 45 for (User user : users) { 46 System.out.println(user); 47 } 48 } 49 50 @Test 51 public void testSave(){ 52 User user = new User(); 53 user.setName("李四"); 54 user.setAddress("江苏省南京"); 55 user.setSex("男"); 56 user.setBirthday(new Date()); 57 58 userDao.saveUser(user); 59 } 60 61 @Test 62 public void testUpdate(){ 63 User user = new User(); 64 user.setId(3); 65 user.setName("李四2"); 66 user.setAddress("江苏省南京2"); 67 user.setSex("男"); 68 user.setBirthday(new Date()); 69 70 userDao.updateUser(user); 71 } 72 73 @Test 74 public void testDelete(){ 75 userDao.deleteUser(6); 76 } 77 78 @Test 79 public void testFindById(){ 80 User user = userDao.findById(3); 81 System.out.println(user); 82 } 83 84 @Test 85 public void testFindByName(){ 86 List<User> users = userDao.findByName("李%"); 87 for (User user : users) { 88 System.out.println(user); 89 } 90 } 91 92 @Test 93 public void testTotal(){ 94 int count = userDao.findTotal(); 95 System.out.println(count); 96 } 97 98 @Test 99 public void testFindByVo(){ 100 QueryVo vo = new QueryVo(); 101 User user = new User(); 102 user.setName("李%"); 103 vo.setUser(user); 104 List<User> users = userDao.findUserByVo(vo); 105 for (User u : users) { 106 System.out.println(u); 107 } 108 } 109 /*@Test 110 public void testFindAll() throws Exception{ 111 //1、读取配置 112 InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); 113 //2、创建SqlSessionFactory工厂 114 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); 115 SqlSessionFactory factory = builder.build(in); 116 //3、使用工厂生产SqlSession对象 117 SqlSession session = factory.openSession(); 118 //4、使用SqlSession创建Dao接口的代理对象 119 IUserDao userDao = session.getMapper(IUserDao.class); 120 //5、使用代理对象执行方法 121 List<User> users = userDao.findAll(); 122 for (User user : users) { 123 System.out.println(user); 124 } 125 //6、释放资源 126 session.close(); 127 in.close(); 128 } 129 130 @Test 131 public void testSave() throws Exception{ 132 User user = new User(); 133 user.setName("张三"); 134 user.setAddress("南京"); 135 user.setSex("男"); 136 user.setBirthday(new Date()); 137 138 //1、读取配置文件,生成输入字节流 139 InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml"); 140 //2、获取SqlSessionFactory 141 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); 142 //3、获取SqlSession对象 143 SqlSession sqlSession = factory.openSession(); 144 //4、获取dao的代理对象 145 IUserDao userDao = sqlSession.getMapper(IUserDao.class); 146 //5、执行 147 userDao.saveUser(user); 148 sqlSession.commit(); 149 sqlSession.close(); 150 in.close(); 151 }*/ 152 }
如果数据库表中的字段和持久层实体类中的字段名称不同怎么办呢?
这时候有3中办法:
- 修改pojo
- 修改数据库中的表
- 也可以修改配置文件
这里说下如果修改配置文件
在mapper中添加resultMap节点
1 <!--配置查询结果的列名和实体类的属性名的对应关系(如果数据库中的字段和pojo中的相同,则这里完全不需要写) 2 然后将下面的resultType全部换成resultMap="userMap" 3 --> 4 <!-- 5 id:唯一标志,随便写 6 type:表示查询的实体类 7 --> 8 <resultMap id="userMap" type="com.mantishell.domain.User"> 9 <!--主键字段的对应--> 10 <id property="id" column="id" /> 11 12 <result property="name" column="name" /> 13 <result property="address" column="address"/> 14 <result property="sex" column="sex"/> 15 <result property="birthday" column="birthday"/> 16 </resultMap>
以查询为例:
原本使用的返回值类型是resultType=全限定类名;使用resultMap后需要将resultType换成resultMap=上面定义的resultMap的id
也就是:
1 <select id="findAll" resultMap="userMap"> 2 select * from user; 3 </select>
注解方式:
在xml配置的基础上,修改3个地方即可:
1、IUserDao.xml删除。
2、dao接口(IUserDao.java)方法上使用注解方式:
1 public interface IUserDao { 2 @Select("select * from user") 3 List<User> findAll(); 4 }
3、SqlMapConfig.xml中mapper配置项修改,去掉resource属性,改为class属性
<mappers>
<mapper class="com.mantishell.dao.IUserDao" />
</mappers>