关于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
,主要配置了数据源等
<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
对象
<mapper namespace="mybatis.test1.userMapper">
<select id="getUser" parameterType="int" resultType="mybatis.test1.User">
select * from users where id=#{id}
select>
mapper>
注意的点:
#{id}
-表示从传递过来的参数中取出id
值namespace
-相当于是唯一标识符,一般是包名+文件名parameterType
-表示参数的类型,这里是int
resultType
表示的是返回值类型,这里是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
标签的顺序
有两种方式实现增删改查操作:
添加数据要使用insert
标签,如下:
insert into users(name, age) values(#{name}, #{age})
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 from users where id=#{id}
测试如下:
int delete = session.delete("mybatis.test2.userMapper.deleteUser", 6);
session.commit();
修改数据使用update
标签
update users set name=#{name}, age=#{age} where id=#{id}
测试如下:
int insert = session.update("mybatis.test2.userMapper.updateUser", new User(4, "xiaowang", 30));
session.commit();
查询单个对象
在xml中的配置如下:
使用selectOne
方法获取查询的对象:
User user = session.selectOne("mybatis.test2.userMapper.getUser", 1);
session.commit();
System.out.println(user);
查询所有对象
查询所有对象,表示返回值有多个对象,resultType
表示list里面放的对象类型
在xml中配置如下:
使用selectList
获取所有对象,测试如下:
List 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 getAll();
}
将接口文件添加到Configuration.xml
的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
中导入文件
在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
中配置全类名的别名
使用别名
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
<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
映射文件:
使用如下方式来获取order对象:
Order order = session.selectOne("mybatis.test4.orderMapper.getOrder", 1);
System.out.println(order);
会发现输出结果为null
如何显示order的查询呢?
1.通过在sql 语句中定义别名
如下给order_id
起别名为id
等等,是表的字段名与实体类属性名对应
这样之后,就可以正常获取值了
Order [id=1, orderNo=aaaa, price=23.0]
2.使用
使用
来把表的字段名与实体类属性名对应
注意此时标签中就要使用
resultMap
(不是resultType
)来对应
标签中id
的值
上面使用的方式是用户比较熟悉的方式。现在有个更好的方式是,使用接口来描述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, '[email protected]')
创建对应的实体类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
内容如下:
<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会为接口创建一个代理对象,代理对象去执行增删改查方法