关于Mybatis的具体介绍请参考http://www.mybatis.org/mybatis-3/zh/
使用Mybatis时,直接导入相应的jar包就行,这里使用的是mybatis-3.4.1.jar
下面的例子,已一个users表为例,先创建表,再插入两条数据
CREATE TABLE users(id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), age INT); INSERT INTO users(NAME, age) VALUES('Tom', 12); INSERT INTO users(NAME, age) VALUES('Jack', 11);创建Mybatis程序的大致步骤是:
1.添加Mybatis 的配置文件Configuration.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="development"> <environment id="development"> <transactionManager type="JDBC"> <property name="" value="" /> </transactionManager> <dataSource type="UNPOOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /> <property name="username" value="root" /> <property name="password" value="" /> </dataSource> </environment> </environments> </configuration>一些说明:
a.transactionManager-事务管理器,在 MyBatis 中有两种类型的事务管理器(也就是 type=”[JDBC|MANAGED]”):
JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)b.dataSource-数据源,dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源
2.创建实体类User和定义操作users 表的sql 映射文件userMapper.xml
首先创建实体类User
public class User { private int id; private String name; private int age; public int getId() { return id; } //get set方法 ...... }然后创建user表的sql映射文件userMapper.xml 在这里定义了一个select语句,根据id查询到一个user对象
<?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="mybatis.test1.userMapper"> <!--根据id查询到一个user对象 --> <select id="getUser" parameterType="int" resultType="mybatis.test1.User"> select * from users where id=#{id} </select> </mapper>注意的点:
#{id}-表示从传递过来的参数中取出id值namespace-相当于是唯一标识符,一般是包名+文件名parameterType-表示参数的类型,这里是intresultType表示的是返回值类型,这里是User类的全类名3.在Configuration.xml文件中注册userMapper.xml 文件
注意:这里是路径的结构,不是包的结构
<mappers> <mapper resource="mybatis/test1/userMapper.xml" /> </mappers>4.执行定义的select 语句
String resource = "Configuration.xml"; //加载mybatis 的配置文件(它也加载关联的映射文件) Reader reader = Resources.getResourceAsReader(resource); //构建sqlSession 的工厂 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); //创建能执行映射文件中sql 的sqlSession SqlSession session = sessionFactory.openSession(); //映射sql 的标识字符串 String statement = "mybatis.test1.userMapper"+".getUser"; //执行查询返回一个唯一user 对象的sql User user = session.selectOne(statement, 1); System.out.println(user);这里的statement是userMapper.xml中mapper的namespace属性,加上select的id属性
String statement = "mybatis.test1.userMapper"+".getUser";最后控制台输出的数据结果为:
User [id=1, name=Tom, age=12]5.输出调用sql语句 为方便调试,可在控制条输出调用sql语句,具体实现参考MyBatis控制台输出SQL语句,注意settings标签的顺序
有两种方式实现增删改查操作:
XML实现注解实现添加数据要使用insert标签,如下:
<insert id="addUser" parameterType="mybatis.test2.User"> insert into users(name, age) values(#{name}, #{age}) </insert> parameterType表示参数的类型使用的是实体类User对象的全类名。values(#{name}, #{age}中#{}括号中对应的是实体类User类的属性编写测试类,测试下:
@Test public void testAdd() { int insert = session.insert("mybatis.test2.userMapper.addUser", new User(-1, "xiaozhao", 23)); System.out.println(insert); }返回值insert表示受影响的行数,此时提示是1,表示是成功的,但是此时去查看数据库,会发现并没有插入的数据。是因为session = sessionFactory.openSession();是需要手动提交事务的,所以需要使用如下的方式:
int insert = session.insert("mybatis.test2.userMapper.addUser", new User(-1, "xiaozhao", 23)); session.commit();设置自动提交
session = sessionFactory.openSession(true);删除数据使用delete标签
<delete id="deleteUser" parameterType="int"> delete from users where id=#{id} </delete>测试如下:
int delete = session.delete("mybatis.test2.userMapper.deleteUser", 6); session.commit();修改数据使用update标签
<update id="updateUser" parameterType="mybatis.test2.User"> update users set name=#{name}, age=#{age} where id=#{id} </update>测试如下:
int insert = session.update("mybatis.test2.userMapper.updateUser", new User(4, "xiaowang", 30)); session.commit();查询单个对象
在xml中的配置如下:
<!--根据id查询到一个uesr对象 --> <select id="getUser" parameterType="int" resultType="mybatis.test2.User"> select * from users where id=#{id} </select>使用selectOne方法获取查询的对象:
User user = session.selectOne("mybatis.test2.userMapper.getUser", 1); session.commit(); System.out.println(user);查询所有对象
查询所有对象,表示返回值有多个对象,resultType表示list里面放的对象类型 在xml中配置如下:
<select id="getAllUsers" resultType="mybatis.test2.User"> select * from users </select>使用selectList获取所有对象,测试如下:
List<User> users = session.selectList("mybatis.test2.userMapper.getAllUsers"); session.commit(); System.out.println(users);基于注解实现,需先定义sql映射的接口,把所有的sql语句写到接口中
package mybatis.test3; import java.util.List; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import mybatis.test2.User; public interface UserMapper { @Insert("insert into users(name, age) values(#{name}, #{age})") public int add(User user); @Delete("delete from users where id=#{id}") public int deleteById(int id); @Update("update users set name=#{name}, age=#{age} where id=#{id}") public int update(User user); @Select("select * from users where id=#{id}") public User getById(int id); @Select("select * from users") public List<User> getAll(); }将接口文件添加到Configuration.xml的mappers中,注意与映射文件的区别
<mappers> <mapper class="mybatis.test3.UserMapper" /> </mappers>测试添加如下:
UserMapper mapper = session.getMapper(UserMapper.class); int add = mapper.add(new User(-1, "xiaoqian", 23)); session.commit(); System.out.println(add);创建db.properties文件
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis username=root password=在Configuration.xml中导入文件
<properties resource="db.properties"></properties>在dataSource标签中引用这些值:
<dataSource type="UNPOOLED"> <property name="driver" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </dataSource>1.定义别名 在上述的的映射文件中,总在重复的写全类名,如mybatis.test1.User,而mybatis.test1.User在很多地方都要重用
<select id="getUser" parameterType="int" resultType="mybatis.test1.User"> select * from users where id=#{id} </select>所以可以在Configuration.xml中配置全类名的别名
<!-- 配置实体类的别名 --> <typeAliases> <typeAlias type="mybatis.test2.User" alias="_User"/> </typeAliases>使用别名
<select id="getAllUsers" resultType="_User"> select * from users </select>2.扫描包方式
参考Mybatis之typeAlias配置的3种方法
通过package, 可以直接指定package的名字, mybatis会自动扫描你指定包下面的javabean, 并且默认设置一个别名,默认的名字为: javabean 的首字母小写的非限定类名来作为它的别名。
<typeAliases> <package name="cn.lxc.vo" /> </typeAliases>3.注解方式
package cn.lxc.vo; import org.apache.ibatis.type.Alias; @Alias("User") public class User { private int id; private String name; private int age; 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 int getAge() { return age; } public void setAge(int age) { this.age = age; } }添加相应的jar包, log4j.properties配置信息如下:
log4j.properties, log4j.rootLogger=DEBUG, Console #Console log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n log4j.logger.java.sql.ResultSet=INFO log4j.logger.org.apache=INFO log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG也可以使用xml方式来配置log4j,如下的log4j.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /> </layout> </appender> <logger name="java.sql"> <level value="debug" /> </logger> <logger name="org.apache.ibatis"> <level value="debug" /> </logger> <root> <level value="debug" /> <appender-ref ref="STDOUT" /> </root> </log4j:configuration>如下的例子中,表中的列名为order_no,而实体类中的属性名为orderNo,如何把它们对应起来呢?
创建如下的orders表:
CREATE TABLE orders( order_id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(20), order_price FLOAT ); INSERT INTO orders(order_no, order_price) VALUES('aaaa', 23); INSERT INTO orders(order_no, order_price) VALUES('bbbb', 33); INSERT INTO orders(order_no, order_price) VALUES('cccc', 22);创建orders表对应的实体类,Order:
package mybatis.bean; public class Order { private int id; private String orderNo; private float price; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getOrderNo() { return orderNo; } public void setOrderNo(String orderNo) { this.orderNo = orderNo; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } public Order() { } public Order(int id, String orderNo, float price) { super(); this.id = id; this.orderNo = orderNo; this.price = price; } @Override public String toString() { return "Order [id=" + id + ", orderNo=" + orderNo + ", price=" + price + "]"; } }可以发现,字段名和属性名并不一致。
创建orderMapper.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="mybatis.test4.orderMapper"> <!--根据id查询到一个order对象 --> <select id="getOrder" parameterType="int" resultType="mybatis.bean.Order"> select * from orders where order_id=#{id} </select> </mapper>使用如下方式来获取order对象:
Order order = session.selectOne("mybatis.test4.orderMapper.getOrder", 1); System.out.println(order);会发现输出结果为null
如何显示order的查询呢? 1.通过在sql 语句中定义别名
如下给order_id起别名为id等等,是表的字段名与实体类属性名对应
<select id="getOrder" parameterType="int" resultType="mybatis.bean.Order"> select order_id id, order_no orderNo, order_price price from orders where order_id=#{id} </select>这样之后,就可以正常获取值了
Order [id=1, orderNo=aaaa, price=23.0]2.使用<resultMap>
使用<resultMap>来把表的字段名与实体类属性名对应
注意此时<select>标签中就要使用resultMap(不是resultType)来对应<resultMap>标签中id的值
<!-- resultMap封装映射关系 --> <resultMap type="mybatis.bean.Order" id="orderMap"> <!-- 针对主键 --> <id property="id" column="order_id"/> <result property="orderNo" column="order_no"/> <result property="price" column="order_price"/> </resultMap> <select id="getOrder" parameterType="int" resultMap="orderMap"> select * from orders where order_id=#{id} </select>上面使用的方式是用户比较熟悉的方式。现在有个更好的方式是,使用接口来描述statement的参数和返回值,这样执行起来可以更简洁和安全
如下的例子,先创建一个tbl_employee表,插入一条数据
create table tbl_employee( id int(11) primary key auto_increment, last_name varchar(255), gender char(1), email varchar(255) ); insert into tbl_employee (last_name, gender, email) values('wz', 0, 'wz@123.com')创建对应的实体类Employee类
public class Employee { private Integer id; private String lastName; private String email; private String gender; //get set方法 ...... }如下先创建一个接口类EmployeeMapper
package com.wz.mybatis.dao; import com.wz.mybatis.bean.Employee; public interface EmployeeMapper { //更加id获取Employee public Employee getEmpById(Integer id); }接口要与映射文件EmpolyeeMapper.xml动态绑定,而对于xml映射文件EmpolyeeMapper.xml要注意:
namespace要指定为接口的全类名select标签的id要与接口的方法名对应EmpolyeeMapper.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="com.wz.mybatis.dao.EmployeeMapper"> <select id="getEmpById" resultType="com.wz.mybatis.bean.Employee"> select id, last_name lastName, gender, email from tbl_employee where id = #{id} </select> </mapper>其调用方式如下:
public SqlSessionFactory getSqlSessionFactory() throws IOException{ String resource = "mybatis-config.xml"; // 加载mybatis 的配置文件(它也加载关联的映射文件) Reader reader = Resources.getResourceAsReader(resource); // 构建sqlSession 的工厂 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader); return sessionFactory; } public void test01() throws IOException { // 构建sqlSession 的工厂 SqlSessionFactory sessionFactory = getSqlSessionFactory(); // 创建能执行映射文件中sql 的sqlSession SqlSession session = sessionFactory.openSession(); try { //获取接口的实现类对象 EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); Employee employee = mapper.getEmpById(1); System.out.println(mapper.getClass()); System.out.println(employee); } finally { session.close(); } }其中System.out.println(mapper.getClass());的控制台输出的结果为class com.sun.proxy.$Proxy4,表示的是Mybatis会为接口创建一个代理对象,代理对象去执行增删改查方法