MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。
MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJOs(Plain Ordinary Java Objects,普通的 Java 对象)映射成数据库中的记录。
MyBatis的前身是iBatis,MyBatis在iBatis的基础上面,对代码结构进行了大量的重构和简化;
package com.mxl.mybatis01_hello;
public class User {
private Long id;
private String username;
private String password;
private Integer age;
public User() {
}
public User(Long id, String username, String password, Integer age) {
this.id = id;
this.username = username;
this.password = password;
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", age=" + age +
'}';
}
}
需要注意的两点是:
1.mapper的namespace中写的是所在包名加上mapper文件名
namespace=“com.mxl.mybatis01_hello.UserMapper”
2.配置自增的id注入对象中
insert into t_user(username,password,age) values (#{username},#{password},#{age})
注意:session.insert中的statement为namespace加id
public class TestCRUD {
@Test
public void test1() throws IOException {
User u = new User();
u.setUsername("撒旦");
u.setPassword("123456");
u.setAge(13);
SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession session = sf.openSession();
session.insert("com.mxl.mybatis01_hello.UserMapper.save",u);
session.commit();
session.close();
System.out.println(u);
}
}
高光处应该写自己的namespace的包名或者父包名.
log4j.logger.com.mxl.mybatis01_hello=TRACE
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.mxl.mybatis01_hello=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
Usermapper.xml中添加:
update t_user set username=#{username},password=#{password},age=#{age} where id = #{id}
测试类中添加:
@Test
public void test2() throws IOException {
User u = new User();
u.setId(1L);
u.setUsername("马欣龙");
u.setPassword("123");
u.setAge(22);
SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession session = sf.openSession();
session.update("com.mxl.mybatis01_hello.UserMapper.update",u);
session.commit();
session.close();
System.out.println(u);
}
此时发现每个测试方法中都要写
SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession session = sf.openSession();
抽取mybatisUtils工具类
public class MybatisUtils {
private SqlSessionFactory sf = null;
private static MybatisUtils instance = new MybatisUtils();
private MybatisUtils(){
try {
sf = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
}catch (Exception e){
e.printStackTrace();
}
}
public static SqlSession openSession(){
return instance.sf.openSession();
}
}
Usermapper.xml中添加:
特别注意:要加resultType:表示查询出来的每一条结果封装成User对象
如果没写则报如下错误:
Caused by: org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the Mapped Statement ‘com.mxl.mybatis01_hello.UserMapper.get’. It’s likely that neither a Result Type nor a Result Map was specified.
测试类中添加:
@Test
public void test3() throws IOException {
SqlSession session = MybatisUtils.openSession();
User u = session.selectOne("com.mxl.mybatis01_hello.UserMapper.get", 3L);
session.close();
System.out.println(u);
}
Usermapper.xml中添加:
测试类中添加:
@Test
public void test4() throws IOException {
SqlSession session = MybatisUtils.openSession();
List list = session.selectList("com.mxl.mybatis01_hello.UserMapper.list");
session.close();
for (User user : list) {
System.out.println(user);
}
}
Usermapper.xml中添加:
delete from t_user where id = #{id}
测试类中添加:
@Test
public void testDelete() throws IOException {
SqlSession session = MybatisUtils.openSession();
session.delete("com.mxl.mybatis01_hello.UserMapper.delete", 2L);
session.commit();
session.close();
}
mybatis中提供了很多别名,比如java.lang.Long的别名为小写的long.
parameterType="long"相当于parameterType=“java.lang.Long”
1.在主配置文件mybatis-config.xml中添加
2.在UserMapper中就可以使用User的别名了
1.新建db.properties文件.
2.主配置文件中使用占位符的方式定义数据库连接信息.
3.在mybatisUtils类中创建sqlsessionfactory的时候传入properties对象
try {
Properties p = new Properties();
p.load(Resources.getResourceAsReader("db.properties"));
sf = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"),p);
}catch (Exception e){
e.printStackTrace();
}
1.新建db.properties文件.
2.直接在主配置文件中配置
①.传入的statement字符串有可能会写错,写错的时候必须等到运行的时候才发现
②.传入的参数无法限定类型.
1.新键UserMapper接口(确保以下几点)
接口的全限定名 等于 UserMapper.xml中的namespace
接口中的方法 等于 UserMapper.xml中标签中的id
接口方法上的参数 等于 UserMapper.xml中的parameterType
接口方法上的返回值类型 等于 UserMapper.xml的resultType
对应的API为:
UserMapper mapper = session.getMapper(UserMapper.class);
当查询出来的字段名和对象中的属性名不一致的情况,就没办法使用resultType来默认映射(同名规则)
解决方案:
使用resultMap来映射数据库中的字段到底注入到对象中什么属性中.
1.在UserMapper.xml文件中定义resultMap标签
2.在查询标签中使用resultMap=”base_map”
创建一个查询对象类QueryObject
public class QueryObject {
private String keyWord;
private Integer beginAge;
private Integer endAge;
//getter setter方法略去
}
在UserMapper.xml中添加如下代码
注意:id中的内容应该与UserMapper接口中的方法名保持一致,否则报错!!!
注意:模糊查询语法like concat(’%’,#{keyWord},’%’)中
concat的使用—单引号的使用
注意:(大于号> >小于号 < <)
注意如果要大于(小于)等于,等于号必须紧跟在>(<)后,中间不能有空格
Usermapper接口中给出相应的方法
List selectByCondition(QueryObject qo);
测试类中给出相应测试方法
@Test
public void testQuery(){
SqlSession session = MybatisUtils.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
QueryObject qo = new QueryObject();
// qo.setKeyWord("东");
qo.setBeginAge(2);
qo.setEndAge(18);
List list = mapper.selectByCondition(qo);
for (User user : list) {
System.out.println(user);
}
session.close();
}
UserMapper.xml中添加如下
该处犯错
首先where不能丢掉
每个if语句后要加上逗号,不加报错!!!
update t_user
username = #{username},
password = #{password},
age = #{age},
where id = #{id}
接口中给出相应的方法
void updateDy(User u);
测试类中编写测试方法
@Test
public void testUpdateDy(){
SqlSession session = MybatisUtils.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User u = new User();
u.setId(8L);
u.setUsername("卡萨丁");
u.setPassword("666");
u.setAge(11);
mapper.updateDy(u);
session.commit();
session.close();
}
prefix表示使用前缀
suffix表示使用的后缀
prefixOverrides表示前缀需要覆盖的内容
suffixOverrides表示后缀需要覆盖的内容
UserMapper.xml中
查询中原来的where可以用trim标签加上特定的属性来替代
动态更新中原来的set可以用trim标签加上特定的属性来替代
update t_user
username = #{username},
password = #{password},
age = #{age},
where id = #{id}
迭代一个集合, 通常是构建在 IN 条件中的
foreach 元素是非常强大的,它允许你指定一个集合,声明集合项和索引变量,它们可 以用在元素体内。它也允许你指定开放和关闭的字符串,在迭代之间放置分隔符。这个元素 是很智能的,它不会附加多余的分隔符。
注意 你可以传递一个 List 实例或者数组作为参数对象传给 MyBatis。当你这么做时 ,MyBatis 会自动将它包装在一个 Map 中,用名称在作为键。List 实例将会以“list” 作为键,而数组实例将会以“array”作为键。
Mapper文件中的代码如下:
open和close配置的是以什么符号将这些集合元素包装起来
collection:选择list集合
separator:是各个元素的间隔符
item:配置的是循环中当前的元素
Mapper接口中
List selectForEach(List idList);
测试类中代码
@Test
public void testForEach() {
SqlSession session = MybatisUtils.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List list = new ArrayList();
list.add(4L);
list.add(5L);
list.add(6L);
list.add(7L);
list.add(8L);
List userList = mapper.selectForEach(list);
for (User user : userList) {
System.out.println(user);
}
session.close();
}
1.编写PageResult类
public class PageResult {
private Long total;
private List rows;
public static final PageResult EMPTY = new PageResult(0L,Collections.emptyList());
public PageResult(Long total, List rows) {
this.total = total;
this.rows = rows;
}
//略去setter和getter方法
}
2.在QueryObject类中添加:
//分页
private Long page;//当前页
private Long row;//每页显示几条数据
//略去getter,setter方法
3.编写IUserService接口
public interface IUserService {
PageResult list(QueryObject qo);
}
4.编写service实现类
public class UserServiceImpl implements IUserService{
public PageResult list(QueryObject qo) {
SqlSession session = MybatisUtils.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
try {
//查询总数
Long count = mapper.selectByConditionCount(qo);
if (count > 0){
List result = mapper.selectByCondition(qo);
return new PageResult(count,result);
}else{
return PageResult.EMPTY;
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
session.close();
}
return null;
}
}
5.在mapper配置文件中
and username like concat('%',#{keyWord},'%')
and age >= #{beginAge}
and age <= #{endAge}
6.测试类
@Test
public void test() throws IOException {
QueryObject qo = new QueryObject();
qo.setKeyWord("东");
qo.setPage(1L);
qo.setRow(2L);
IUserService service = new UserServiceImpl();
PageResult page = service.list(qo);
System.out.println("总记录数: "+page.getTotal());
List rows = page.getRows();
for (User u : rows) {
System.out.println(u);
}
}
}