目录
一、iBatis历史演变
iBatis时代是一个以iBatis为主导的持久层框架发展时期。Mybatis的前身为iBatis。
iBatis一词来源于“internet”和“abatis”的组合,是一个由Clinton Begin在2001年发起的开放源代码项目。它的目标是提供一种灵活且易于使用的持久层框架,用于Java和.NET平台。
iBatis是由Clinton Begin在2001年发起的开源项目,在2002年,iBatis项目被捐献给Apache软件基金会,这一举措极大地推动了iBatis在方法论、源码管理、社交、开源基础建设等方面的进步。在Apache的庇护下,iBatis不断迭代更新,引入了许多新特性和改进。例如,iBATIS 2.0版本在2004年发布,随后发布了多个更新版本,直到iBATIS 3.0的发布。
2010年,随着iBatis 3.0版本的发布,开发团队决定将其迁移到谷歌托管,并正式更名为MyBatis。这一更名不仅反映了项目的新阶段,也标志着项目在稳定性和性能方面有了显著提升。
2010年6月16日,MyBatis项目被正式归入Apache Attic,属性变为“只读”,这意味着该项目在iBatis时代正式结束。为了吸引更多的贡献者和用户,MyBatis项目于2013年11月10日被迁移至GitHub。GitHub作为全球最大的开源代码托管平台之一,为MyBatis项目提供了更广阔的舞台和更丰富的资源。
二、新建Module
1. 搭建框架
2. 导入lib包
链接: https://pan.baidu.com/s/11vCiuRNEbGM0hSqZgEDSWQ 提取码: t9q8
3. 配置log4j.properties文件
记录应用程序的日志信息
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=debug, stdout
4.导入数据库文件
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for ly_user
-- ----------------------------
DROP TABLE IF EXISTS `gxa_user`;
CREATE TABLE `ly_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`salt` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`created` datetime(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0),
`last_login_time` datetime(0) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(0),
`status` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
-- ----------------------------
-- Records of ly_user
-- ----------------------------
INSERT INTO `ly_user` VALUES ('1', '吴优雅', 'RbWEEsXVVxiR765qwusODQ==', 'e46d82f4-66b1-457d-8e70-36232b0a656e', 'sada@126.com', '2020-11-24 21:18:04', '2020-11-24 21:18:04', '1');
INSERT INTO `ly_user` VALUES ('2', '林老师', 'RbWEEsXVVxiR765qwusODQ==', 'e46d82f4-66b1-457d-8e70-36232b0a656e', 'sada@126.com', '2020-11-24 21:18:48', '2020-11-24 21:18:48', '1');
INSERT INTO `ly_user` VALUES ('3', '强哥', 'RbWEEsXVVxiR765qwusODQ==', 'e46d82f4-66b1-457d-8e70-36232b0a656e', 'sada@126.com', '2020-11-24 21:19:11', '2020-11-24 21:19:11', '1');
三、编写工具类
package com.ly.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
/**
* Created by ly on 2024/9/25
*/
public class MyBatisUtils {
private static SqlSessionFactory sqlSessionFactory;
//存放当前线程都的SqlSession对象
private static ThreadLocal<SqlSession> tl=new ThreadLocal<>();
static {
try {
//1.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//2.读取xml
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//3.创建SqlSessionFactory对象
sqlSessionFactory= sqlSessionFactoryBuilder.build(in);
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException("加载配置文件失败!");
}
}
/**
* 获取当前线程的sqlSession
* @return
*/
public static SqlSession getSqlSession(){
SqlSession sqlSession = tl.get();
//如果当前线程没有sqlSession,新获取一个SqlSession,绑定到当前线程
if(sqlSession==null){
//默认已经开启了手动事务
sqlSession=sqlSessionFactory.openSession();
//绑定sqlSession到当前线程
tl.set(sqlSession);
}
return sqlSession;
}
/**
* 提交事务
*/
public static void commitTransaction(){
SqlSession sqlSession = tl.get();
if(sqlSession!=null){
//提交事务
sqlSession.commit();
}
}
/**
* 回滚事务
*/
public static void rollbackTransaction(){
SqlSession sqlSession = tl.get();
if(sqlSession!=null){
sqlSession.rollback();
sqlSession.commit();
}
}
/**
* 关闭sqlSession&移除当前线程绑定的sqlSession
*/
public static void closeSqlSession(){
SqlSession sqlSession = tl.get();
if(sqlSession!=null){
tl.remove();
sqlSession.close();
}
}
}
三、编写dao接口
package com.ly.dao;
import com.ly.pojo.User;
import java.util.List;
/**
* Created by ly on 2024/9/25
*/
public interface UserDao {
User findUserById(Long id);
List<User> findUserByUsername(String username);
int insertUser(User user);
int updateUser(User user);
int deleteUserById(Long id);
}
四、编写dao的实现类
package com.ly.dao.impl;
import com.ly.dao.UserDao;
import com.ly.pojo.User;
import com.ly.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
/**
* Created by ly on 2024/9/25
*/
public class UserDaoImpl implements UserDao {
@Override
public User findUserById(Long id) {
//1.获取当前线程线程的sqlSession
SqlSession sqlSession = MyBatisUtils.getSqlSession();
return sqlSession.selectOne("com.ly.dao.UserDao.findUserById",id);
}
@Override
public List<User> findUserByUsername(String username) {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
return sqlSession.selectList("com.ly.dao.UserDao.findUserByUsername",username);
}
@Override
public int insertUser(User user) {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
return sqlSession.insert("com.ly.dao.UserDao.insertUser",user);
}
@Override
public int updateUser(User user) {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
return sqlSession.update("com.ly.dao.UserDao.updateUser",user);
}
@Override
public int deleteUserById(Long id) {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
return sqlSession.delete("com.ly.dao.UserDao.deleteUserById",id);
}
}
五、编写xml
编写SqlMapConfig.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>
<!-- mybatis和spring整合过后废除 -->
<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/crud?characterEncoding=UTF-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="User.xml"></mapper>
</mappers>
</configuration>
编写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">
<!-- 命名空间,用于隔离sql,后面还有一个很重要的作用 -->
<mapper namespace="com.ly.dao.UserDao">
<!--select标签,查询-->
<!--id sql的唯一标记 在一个命名空间下唯一-->
<!--parameterType:输入参数的类型-->
<!--resultType:输出参数的类型-->
<!--#{}占位符 底层还是使用prepareStatement设置参数-->
<select id="findUserById" parameterType="long" resultType="com.ly.pojo.User">
select * from ly_user where id=#{id}
</select>
<select id="findUserByUsername" parameterType="string" resultType="com.ly.pojo.User">
select * from ly_user where username like CONCAT('%',#{usenrame},'%')
</select>
<!--如果parameterType传递的是pojo类型,#{}中写的是pojo的属性值-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id" keyColumn="id" parameterType="com.ly.pojo.User">
<!--selectKey查询主键-->
<!--keyColumn:主键对应数据库的哪一列-->
<!--keyProperty:主键对应pojo哪一个属性-->
<!--order:在插入语句之前执行还是之后执行-->
<!--resultType:配置主键的类型-->
<!-- <selectKey keyColumn="id" keyProperty="id" order="AFTER" resultType="long">-->
<!-- select LAST_INSERT_ID()-->
<!-- </selectKey>-->
insert into ly_user(username,password,salt,phone,created,last_login_time,status) values(#{username},#{password},#{salt},#{phone}
,#{created},#{lastLoginTime},#{status})
</insert>
<update id="updateUser" parameterType="com.ly.pojo.User">
update ly_user set username=#{username},password=#{password},last_login_time=#{lastLoginTime} where id=#{id}
</update>
<delete id="deleteUserById" parameterType="long">
delete from ly_user where id=#{id}
</delete>
</mapper>
六、测试
package junit.test;
import com.ly.dao.UserDao;
import com.ly.dao.impl.UserDaoImpl;
import com.ly.pojo.User;
import com.ly.utils.MyBatisUtils;
import org.junit.Test;
import java.io.IOException;
import java.util.Date;
/**
* Created by ly on 2024/9/25
*/
public class TestUserDao {
private UserDao userDao=new UserDaoImpl();
@Test
public void testFind() throws IOException {
User user = userDao.findUserById(3L);
System.out.println(user);
}
@Test
public void testInsert() throws IOException {
User user=new User(null,"龙龙","123456","xxx","xxxx",new Date(),new Date(),1);
int i = userDao.insertUser(user);
System.out.println(i);
//提交事务
MyBatisUtils.commitTransaction();
}
}
testFind()
testInsert()
七、思考
dao实现类存在大量重复的代码!!!
mybatis可不可以使用动态代理帮我们去生成实现类的代码!!! 可以
1.接口的方法名和sql的id一致
2.xml中的namespace要和接口的全限定名一致
3.接口参数类型要和parameterType类型一致
4.接口的返回值类型和resultType类型一致