Mybatis入门
下载
Mybaits的代码由github管理,本实例采用3.2.7版本,传送门:https://github.com/mybatis/mybatis-3/releases/download/mybatis-3.2.7/mybatis-3.2.7.zip
目录结构
lib------mybatis的依赖包
mybatis-3.2.7.jar------核心包
mybatis-3.2.7.pdf------使用手册
工程搭建
创建java工程
创建java工程,并新建lib文件夹,如下图所示
加入jar包
加入mybatis核心包、依赖包、数据驱动包、Junit包(共12个)
添加jar包到构建路径:全选jar包>右键>Build Path>Add to Build Path
log4j.properties
在classpath下创建log4j.properties如下:
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# 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
mybatis默认使用log4j作为输出日志信息。
SqlMapConfig.xml
SqlMapConfig.xml是mybatis核心配置文件,上边文件的配置内容为数据源、事务管理。
<?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>
<!-- 和spring整合后 environments配置将废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
</configuration>
实体类
Po类作为mybatis进行sql映射使用,po类通常与数据库表对应,User.java如下:
Public class User {
private int id;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
get/set……
sql映射文件
在classpath下创建User.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">
<!-- namespace:命名空间,做sql隔离 -->
<mapper namespace="test">
</mapper>
namespace :命名空间,用于隔离sql语句,防止查询语句重名
加载映射文件
mybatis框架需要加载映射文件,将Users.xml添加在SqlMapConfig.xml,如下:
<mappers>
<mapper resource="sqlmap/User.xml"/>
</mappers>
创建数据库
创建一个名为mybatis的数据库,采用UTF-8编码
以下是表结构
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`sex` varchar(255) DEFAULT NULL,
`birthday` date DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;
查询
根据id查询用户信息
映射文件
在User.xml中添加:
<!-- 根据id获取用户信息 -->
<select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
select * from user where id = #{id}
</select>
id:sql语句唯一标识
parameterType:定义输入到sql中的映射类型,#{id}表示使用preparedstatement设置占位符号并将输入变量id传到sql。
resultType:定义结果映射类型。
#{}占位符:起到占位作用,如果传入的是基本类型(string,long,double,int,boolean,float等),那么#{}中的变量名称可以随意写。
Junit测试用例执行前环境获取程序
public class UserTest {
//会话工厂
private SqlSessionFactory sqlSessionFactory;
@Before
public void createSqlSessionFactory() throws IOException{
// 配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 使用SqlSessionFactoryBuilder从xml配置文件中创建SqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
}
测试用例程序
@Test
public void testFindUserById() throws Exception{
// 数据库会话实例
SqlSession sqlSession = sqlSessionFactory.openSession();
//第一个参数:所调用的sql语句= namespace+.+sql的ID
User user = sqlSession.selectOne("test.findUserById", 1);
System.out.println(user);
if(sqlSession!=null){
sqlSession.close();
}
}
根据用户名查询用户信息
映射文件
在User.xml中添加:
<!-- 自定义条件查询用户列表 -->
<select id="findUserByUsername" parameterType="java.lang.String" resultType="cn.mybaits.pojo.User">
select * from user where username like '%${value}%'
</select>
测试用例程序
@Test
public void testFindUserByUsername(){
// 数据库会话实例
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> list = sqlSession.selectList("test.findUserByUsername","张");
System.err.println(list.size());
if(sqlSession!=null){
sqlSession.close();
}
}
parameterType:定义输入到sql中的映射类型,
value表示使用参数将
{value}替换,做字符串的拼接。
注意:如果是取简单数量类型的参数,括号中的值必须为value
resultType:定义结果映射类型。
小结
#{}和${}
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。#{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
parameterType和resultType
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。
selectOne和selectList
selectOne:
查询一条记录,如果使用selectOne查询多条记录则抛出异常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)
selectList:
可以查询一条或多条记录。
增删改
添加
映射文件
在User.xml中添加
<!-- 添加用户 -->
<insert id="insertUser" parameterType="cn.mybaits.pojo.User">
insert into user(username, birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address})
</insert>
测试程序
@Test
public void testInsertUser(){
// 数据库会话实例
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setUsername("狗群");
user.setBirthday(new Date());
user.setSex("雄性");
user.setAddress("河南郑州动物园");
sqlSession.insert("test.insertUser",user);
sqlSession.commit();//提交事务
if(sqlSession!=null){
sqlSession.close();
}
}
mysql自增主键返回
映射文件
通过修改sql映射文件,添加selectKey可以实现将mysql自增主键返回:
<!-- 添加用户 -->
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<!-- selectKey将主键返回,需要再返回 -->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
insert into user(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address});
</insert>
keyProperty:返回的主键存储在pojo中的哪个属性。
order:selectKey的执行顺序,是相对与insert语句来说,由于mysql的自增原理执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为after。
resultType:返回的主键是什么类型。
AST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。
测试程序
@Test
public void testInsertUser(){
// 数据库会话实例
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setUsername("狗群");
user.setBirthday(new Date());
user.setSex("雄性");
user.setAddress("河南郑州动物园");
sqlSession.insert("test.insertUser",user);
sqlSession.commit();//提交事务
System.err.println(user.getId());
if(sqlSession!=null){
sqlSession.close();
}
}
Mysql使用 uuid实现主键
略
删除
映射文件
<!-- 删除用户 -->
<delete id="deleteUserById" parameterType="int">
delete from user where id=#{id}
</delete>
测试程序
@Test
public void testDeleteUser(){
// 数据库会话实例
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("test.deleteUser",15);
sqlSession.commit();//提交事务
if(sqlSession!=null){
sqlSession.close();
}
}
修改
映射文件
<!-- 更新-->
<update id="updateUser" parameterType="cn.mybaits.pojo.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
where id=#{id}
</update>
测试程序
@Test
public void testUpdateUser(){
// 数据库会话实例
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setId(16);//必须指定id
user.setUsername("狗群");
user.setBirthday(new Date());
user.setSex("雌性");
user.setAddress("河南郑州动物园2号监狱");
sqlSession.update("test.updateUser", user);
sqlSession.commit();//提交事务
System.err.println(user.getId());
if(sqlSession!=null){
sqlSession.close();
}
}
总结
Mybatis解决传统jdbc编程的问题
1、数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
解决:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。
2、ql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
3、向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。
4、对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。
mybatis与hibernate不同
hibernate:它是一个标准的orm框架,比较重量级,学习成本高。
优点:高度封装,使用起来不用写sql,开发的时候,会减低开发周期。
缺点:sql语句无法优化
应用场景:oa(办公自动化系统), erp(企业的流程系统)等,还有一些政府项目,在用于量不大,并发量小的时候使用。
mybatis:它不是一个orm框架, 它是对jdbc的轻量级封装, 学习成本低,比较简单
优点:学习成本低, sql语句可以优化, 执行效率高,速度快
缺点:编码量较大,会拖慢开发周期
应用场景: 互联网项目,比如电商,P2p等总的来说是用户量较大,并发高的项目
按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。