在pom.xml中引入相关依赖
<groupId>com.dz</groupId>
<artifactId>mybatis_test</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--MyBatis核心依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!--MySQL核心依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<!--日志依赖: log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency><!--测试依赖: junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<!--更改maven的编译规则-->
<resources>
<resource>
<!--资源目录-->
<directory>src/main/java</directory>
<includes>
<include>*.xml</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
src > main > resources 下创建并配置mybatis-config.xml
<!--导入外部的参数-->
<properties resource="jdbc.properties"/>
<!--实体类别名-->
<typeAliases>
<!--<typeAlias type="com.dz.entity.User" alias="user_1"/>-->
<package name="com.dz.entity"/>
</typeAliases>
<!--环境配置,连接的数据库,这里使用的是MySQL-->
<environments default="mysql">
<!--数据库相关配置-->
<environment id="mysql">
<!--事务控制类型-->
<transactionManager type="jdbc"/>
<!--数据连接参数 连接池-->
<dataSource type="org.apache.ibatis.datasource.pooled.PooledDataSourceFactory">
<property name="driver" value="${jdbc.driver}"/>
<!--& 转义 &-->
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--注册mapper文件-->
<mappers>
<!--注册mapper文件的所在位置-->
<mapper resource="UserDaoMapper.xml"/>
<mapper resource="StudentDaoMapper.xml"/>
<mapper resource="PassengerDaoMapper.xml"/>
<mapper resource="PassportDaoMapper.xml"/>
<mapper resource="DepartmentDaoMapper.xml"/>
<mapper resource="EmployeeDaoMapper.xml"/>
<mapper resource="SubjectsDaoMapper.xml"/>
<mapper resource="StudentsDaoMapper.xml"/>
</mappers>
注意: mapper.xml文件默认存放在resources目录中,路径不能以 / 开头
如果放在其他目录下
放在其他目录下可能出现错误:
1 字节的 UTF-8 序列的字节 1 无效
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_db?useUnicode=true&useSSL=false&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=8031
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# 配置stdout输出到控制台
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
# 配置stdout设置为自定义布局模式
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# 配置stdout日志的输出格式 2021-05-01 23:45:26,166 %p日志的优先级 %t线程名 %m日志 %n换行
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} - %5p [%t] - %m%n
create table t_user
(
id int auto_increment
primary key,
username varchar(50) null,
password varchar(50) null,
gender tinyint null,
register_time datetime null
);
定义所需CURD操作的实体类
package com.dz.entity;
import java.util.Date;
public class User {
private Integer id;
private String username;
private String password;
private Boolean gender;
private Date registTime;
public User() {
}
public User(Integer id, String username, String password, Boolean gender, Date registTime) {
this.id = id;
this.username = username;
this.password = password;
this.gender = gender;
this.registTime = registTime;
}
//下方的Getter and Setter这里省略
package com.dz.dao;
import com.dz.entity.User;
public interface UserDao {
//查询
User queryUserById(Integer id);
}
在resources目录下创建UserDaoMapper.xml文件
将UserDaoMapper.xml注册到mybatis-config.xml中( 4.2小节中已经配置)
MyBatis的API操作方式
package com.dz.test;
import com.dz.dao.UserDao;
import com.dz.entity.User;
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.IOException;
import java.io.InputStream;
@Test
public static void test() throws IOException {
//MyBatis API
//1. 加载配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");//2. 构建 SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//3. 通过SqlSessionFactory 创建 SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//4. 通过SqlSession 获得 Dao实现类的对象
UserDao mapper = sqlSession.getMapper(UserDao.class);//获得UserDao 对应实现类的对象
//5. 调用接口中的方法
System.out.println(mapper.queryUserById(1));
}
在pom.xml文件最后追加< build>标签, 以便可以将xml文件复制到classes中, 并在程序运行时正确读取
<build>
<!--更改maven的编译规则-->
<resources>
<resource>
<!--资源目录-->
<directory>src/main/java</directory>
<includes>
<include>*.xml</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
对于mybatis-config.xml的核心配置中, 如果存在需要频繁改动的数据内容, 可以提取到properties中 (4.2小节中已经配置)
#jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_db?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=8031
为实体类定义别名, 提高书写效率(4.2小节中已经配置)
pom.xml中添加log4j依赖 (4.1小节已配置)
创建并配置log4j.properties
log4j.rootLogger=DEBUG, stdout
log4j.logger.org.mybatis.example.BlogMapper=TRACE
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} - %5p [%t] - %m%n
级别
public interface UserDao {
//使用原生参数绑定
User queryUserByIdAndUsername(Integer id, String username);//参数arg 从0开始
User queryUserByIdAndUsername1(Integer id, String username);//参数param 从1开始
}
<select id="queryUserByIdAndUsername" resultType="User">
select id,username,password,gender,register_time registTime
where id=#{arg0} and username=#{arg1}
</select>
<select id="queryUserByIdAndUsername1" resultType="User">
select id,username,password,gender,register_time registTime
where id=#{param1} and username=#{param2}
</select>
import org.apache.ibatis.annotations.Param;//引入注解
public interface UserDao {
//使用MyBatis提供的@param进行参数绑定
User queryUserByIdAndPassword(@Param("id") Integer id, @Param("password") String password);
}
<select id="queryUserByIdAndPassword" resultType="User">
select id,username,password,gender,register_time registTime
from t_user
where id=#{id} and password=#{password}
</select>
import java.util.Map;
public interface UserDao {
//添加Map进行参数绑定
//通过key获得value
User queryUserByIdAndUsername2(Map map);
}
<select id="queryUserByIdAndUsername2" resultType="User">
select id,username,password,gender,register_time registTime
from t_user
where id=#{id} and username=#{username}
</select>
//4. Map集合
Map map = new HashMap();
map.put("id", 1);
map.put("username", "dz1");
User user4 = mapper.queryUserByIdAndUsername2(map);
System.out.println(user4);
public interface UserDao {
//使用对象属性进行参数绑定
//取user对象的id属性值和password属性值
User queryUserByIdAndPassword2(User user);
}
<select id="queryUserByIdAndPassword2" resultType="User">
select id,username,password,gender,register_time registTime
from t_user
where id=#{id} and password=#{password}
</select>
public interface UserDao {
//模糊查询 使用concat 拼接 %
List<User> queryUserByUsername(@Param("username") String username);
}
<select id="queryUserByUsername" resultType="User">
select id,username,password,gender,register_time registTime
from t_user
where username like concat('%', #{username}, '%')
</select>
标签: < delete id="" parameterType="">
标签: < update id="" parameterType="">
标签: < insert id="" parameterType="">
适用于整数类型自增主键
适用于字符串类型自增主键
create table t_student
(
id varchar(32) not null
primary key,
name varchar(50) null,
gender tinyint null
);
package com.dz.entity;
public class Student {
private String id;
private String name;
private Boolean gender;
//Getter and Setter…
}
Resources: 用于获得读取配置文件的IO对象, 耗费资源, 建议通过IO一次性读取所有所需要的数据
SqlSessionFactory: SqlSession工厂类, 内存占用多, 耗费资源, 建议每个应用只创建一个对象
SqlSession: 相对于Connection, 可控制事务, 应为线程私有, 不被多线程共享
将获得连接, 关闭连接, 提交事务, 回滚事务, 获得接口实现类等方法进行封装
package com.dz.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.IOException;
import java.io.InputStream;
/**
public class MyBatisUtil {
//获得SqlSession工厂
private static SqlSessionFactory sqlSessionFactory;
//创建ThreadLocal 绑定当前线程中的SqlSession对象
private static final ThreadLocal
static {//加载配置信息, 并构建session工厂
//1. 加载配置文件
try {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获得连接 (从THREAD_LOCAL中获得当前线程的sqlSession)
public static SqlSession openSession() {
SqlSession sqlSession = THREAD_LOCAL.get();
if (sqlSession == null) {
sqlSession = sqlSessionFactory.openSession();
THREAD_LOCAL.set(sqlSession);
}
return sqlSession;
}
//释放连接 (释放当前线程中的sqlSession)
public static void closeSession() {
SqlSession sqlSession = THREAD_LOCAL.get();
sqlSession.close();
THREAD_LOCAL.remove();
}
//提交事务 (提交当前线程中的sqlSession所管理的事务)
public static void commit() {
SqlSession sqlSession = openSession();
sqlSession.commit();
closeSession();
}
//回滚事务 (回滚当前线程中的sqlSession所管理的事务)
public static void rollback() {
SqlSession sqlSession = openSession();
sqlSession.rollback();
closeSession();
}
//获得接口实现类对象
public static <T> T getMapper(Class<T> mapper) {
SqlSession sqlSession = openSession();
return sqlSession.getMapper(mapper);
}
}
调用MyBatisUtil中的封装方法
package com.dz.test;
import com.dz.dao.UserDao;
import com.dz.entity.User;
import com.dz.utils.MyBatisUtil;
import org.junit.Test;
import java.util.Date;
import java.util.List;
public class MyBatisTest {
@Test
public void test() {
UserDao mapper = MyBatisUtil.getMapper(UserDao.class);
User user = mapper.queryUserByIdAndUsername(3, "bbb");
List
System.out.println(user);
for (User user1 : users) {
System.out.println(user1);
}
System.out.println(mapper.queryUserById(3));
}
@Test
public void test1() {
UserDao mapper = MyBatisUtil.getMapper(UserDao.class);
User user = new User(null,"jack","123",true,new Date());
mapper.insertUser(user);
System.out.println(user.getId());
MyBatisUtil.commit();
}
}
在SQL中使用 as 为查询字段添加列的别名, 以匹配属性名
或者把as省略, 直接在想要添加别名的列后面 写上别名
结果映射(ResultMap 查询结果的封装规则)
通过< resultMap id="" type="">映射, 匹配列名与属性名
实体间的关系: 关联关系(拥有 has, 属于 belong)
create table t_passenger
(
id int auto_increment
primary key,
name varchar(50) null,
sex varchar(1) null,
birthday date null
);
create table t_passport
(
id int auto_increment
primary key,
nationality varchar(50) null,
expire date null,
passenger_id int null,
constraint passenger_id
unique (passenger_id),
constraint t_passport_ibfk_1
foreign key (passenger_id) references t_passenger (id)
);
package com.dz.entity;
import java.util.Date;
public class Passenger {
private Integer id;
private String name;
private Boolean sex;
private Date birthday;
//存储旅客的护照信息: 关系属性
private Passport passport;
//Getter and Setter...
}
package com.dz.entity;
import java.util.Date;
public class Passport {
private Integer id;
private String nationality;
private Date expire;
//存储旅客信息: 关系属性
private Passenger passenger;
//Getter and Setter
}
关系属性: 将关系的另一方, 作为本方属性进行保存
关系方向:
级联查询
当访问其中的一方关系时, 如果需要查看与之关联的另一方数据, 则必须使用表连接查询, 将查询到的另一方数据, 保存在本方的属性中
一个乘客对应一本护照, 反之亦然
package com.dz.dao;
import com.dz.entity.Passenger;
import org.apache.ibatis.annotations.Param;
public interface PassengerDao {
//通过旅客id查询旅客信息和其护照信息 关联查询, 级联查询
Passenger queryPassengerById(@Param("id") Integer id);
}
<!--关系表中数据的封装规则 指定关系表的实体类型-->
<!--描述passId nationality expire 和 passport 的映射规则-->
<association property="passport" javaType="Passport">
<id column="passId" property="id"/>
<result column="nationality" property="nationality"/>
<result column="expire" property="expire"/>
</association>
</resultMap>
<!--多表连接查询--> <!--结果映射(查询结果的封装规则)-->
<select id="queryPassengerById" resultMap="passenger_passport">
select t_passenger.id,name,sex,birthday,t_passport.id passId,nationality,expire
from t_passenger join t_passport
on t_passenger.id = t_passport.passenger_id
where t_passenger.id = #{id}
</select>
注意: 指定"一方"关系时 (对象), 使用< association javaType="">
一个部门对应多个员工, 一个员工对应一个部门
package com.dz.entity;
import java.util.List;
public class Department {
private Integer id;
private String name;
private String location;
//部门内的员工信息
private List
//…
}
package com.dz.entity;
public class Employee {
private Integer id;
private String name;
private Double salary;
//员工所属部门信息
private Department department;
//…
}
<resultMap id="dept_emp" type="Department">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="location" property="location"/><!--emp_id emp_name salary employees-->
<collection property="employees" ofType="Employee">
<id column="emp_id" property="id"/>
<result column="emp_name" property="name"/>
<result column="salary" property="salary"/>
</collection>
</resultMap>
<select id="queryDepartmentById" resultMap="dept_emp">
select t_department.id,t_department.name,location,t_employee.id emp_id,t_employee.name emp_name,salary
from t_department join t_employee
on t_department.id = t_employee.dept_id
where t_department.id=#{id}
</select>
注意: 指定"多方"关系时 (集合), 使用< collection ofType="">
一个学生对应很多科目, 一个科目也对应很多学生
建立三张关系表,学生表, 科目表, 学生科目id表
create table t_students
(
id int auto_increment
primary key,
name varchar(50) null,
sex varchar(1) null
);
create table t_subjects
(
id int auto_increment
primary key,
name varchar(50) null,
grade int null
);
create table t_stu_sub
(
student_id int not null,
subject_id int not null,
primary key (student_id, subject_id),
constraint t_stu_sub_ibfk_1
foreign key (student_id) references t_students (id),
constraint t_stu_sub_ibfk_2
foreign key (subject_id) references t_subjects (id)
);
<collection property="subjects" ofType="Subjects">
<id column="sub_id" property="id"/>
<result column="sub_name" property="name"/>
<result column="grade" property="grade"/>
</collection>
</resultMap>
<select id="queryStudentsById" resultMap="students_subjects">
select t_students.id,t_students.name,sex,t_subjects.id sub_id,t_subjects.name sub_name,grade
from t_students join t_stu_sub
on t_students.id = t_stu_sub.student_id
join t_subjects
on t_stu_sub.subject_id = t_subjects.id
where t_students.id = #{id}
</select>
注意: 指定"多方"关系时 (集合), 使用< collection ofType="">
<mapper namespace="com.dz.dao.UserDao">
<!--抽取重复的sql片段-->
<sql id="user_sql">
select id,username,password,gender,register_time
from t_user
</sql>
<select id="queryUserById" resultType="User">
<include refid="user_sql"/><!--通过id引用SQL片段-->
where id=#{arg0}
</select>
</mapper>
<!--where标签
1. 补充where关键字
2. where 元素知道只有在一个及以上的if条件有值的情况下才去插入“WHERE”子句。
而且,若最后的内容是“AND”或“OR”开头的,where 元素也知道如何将他们去除-->
<select id="queryUser2" resultMap="user_resultMap">
<include refid="user_sql"/>
<where>
<if test="username!=null">
username=#{username}
</if>
<if test="gender!=null">
or gender=#{gender}
</if>
</where>
</select>
<update id="updateUser" parameterType="User">
update t_user
<!--set标签
1. 补充set
2. 自动将set子句中最后的逗号去除
-->
<set>
<if test="username!=null">
username=#{username},
</if>
<if test="password!=null">
password=#{password},
</if>
<if test="gender!=null">
gender=#{gender},
</if>
<if test="registTime!=null">
register_time=#{registTime}
</if>
</set>
</update>
<select id="queryUser2" resultMap="user_resultMap">
<include refid="user_sql"/>
<!--prefix="where" 补充关键字
prefixOverrides="or|and" 若最后的内容是“AND”或“OR”开头的,会将他们覆盖
-->
<trim prefix="where" prefixOverrides="or|and">
<if test="username!=null">
username=#{username}
</if>
<if test="gender!=null">
or gender=#{gender}
</if>
</trim>
</select>
<update id="updateUser" parameterType="User">
update t_user
<!--prefix="set" 补充关键字
suffixOverrides="," 自动将set子句中最后的逗号去除
-->
<trim prefix="set" suffixOverrides=",">
<if test="username!=null">
username=#{username},
</if>
<if test="password!=null">
password=#{password},
</if>
<if test="gender!=null">
gender=#{gender},
</if>
<if test="registTime!=null">
register_time=#{registTime}
</if>
</trim>
where id=#{id}
</update>
参数
collection: 容器类型
open: 起始符
close: 结束符
separator: 分隔符
index: 下标号
item: 当前项
package com.dz.dao;
import com.dz.entity.User;
import java.util.List;
public interface UserDao {
Integer insertManyUser(List<User> users);
}
<delete id="deleteManyUser" parameterType="java.util.List">
<!--delete from t_user where id in (x,x,x,x,x,x)-->
delete from t_user where id in
<foreach collection="list" open="(" close=")" item="id9" separator=",">
#{id9}
</foreach>
</delete>
public class MyBatisTest {
private UserDao mapper;
@Before
public void init() {
mapper = MyBatisUtil.getMapper(UserDao.class);
}
@Test
public void test4() {
//批量删除
List<Integer> ids = Arrays.asList(1000,1001);
mapper.deleteManyUser(ids);
MyBatisUtil.commit();
}
}
package com.dz.dao;
import com.dz.entity.User;
import java.util.List;
public interface UserDao {
Integer insertManyUser(List<User> users);
}
<insert id="insertManyUser" parameterType="java.util.List">
<!--insert into t_user (null,x,x,x,x) values(null,x,x,x)-->
insert into t_user values
<foreach collection="list" open="" close="" item="user9" separator=",">
(null,#{user9.username},#{user9.password},#{user9.gender},#{user9.registTime})
</foreach>
</insert>
public class MyBatisTest {
private UserDao mapper;
@Before
public void init() {
mapper = MyBatisUtil.getMapper(UserDao.class);
}
@Test
public void test5() {
List<User> users = Arrays.asList(new User(null, "dz1", "123", true, new Date()),
new User(null, "dz2", "123", false, new Date()),
new User(null, "dz3", "123", true, new Date()));
mapper.insertManyUser(users);
MyBatisUtil.commit();
}
}
< setting > 是MyBatis中极为重要的调整设置, 他们会改变MyBatis的运行行为, 其他详细配置可参考官方文档
<mapper namespace="com.dz.dao.UserDao">
<!--二级缓存是默认开启的, 但不是所有的查询结果, 都会进入二级缓存-->
<cache/>
<select id="queryUserById" resultType="User">
select id,username,password,gender,register_time as registTime
from t_user
where id=#{arg0}
</select>
</mapper>
@Test
public void test7() {
//通过形同的SqlSessionFactory获取多个SqlSession
SqlSession session1 = MyBatisUtil.getSession();
SqlSession session2 = MyBatisUtil.getSession();
SqlSession session3 = MyBatisUtil.getSession();
UserDao mapper1 = session1.getMapper(UserDao.class);
UserDao mapper2 = session2.getMapper(UserDao.class);
UserDao mapper3 = session3.getMapper(UserDao.class);
mapper1.queryUsers();
session1.close();//必须关闭sqlSession才可缓存数据
System.out.println("=============");
mapper2.queryUsers();
session2.close();//必须关闭sqlSession才可缓存数据
System.out.println("=============");
mapper3.queryUsers();
session3.close();//必须关闭sqlSession才可缓存数据
}
@Test
public void test7() {
//通过形同的SqlSessionFactory获取多个SqlSession
SqlSession session1 = MyBatisUtil.getSession();
SqlSession session2 = MyBatisUtil.getSession();
SqlSession session3 = MyBatisUtil.getSession();
UserDao mapper1 = session1.getMapper(UserDao.class);
UserDao mapper2 = session2.getMapper(UserDao.class);
UserDao mapper3 = session3.getMapper(UserDao.class);
mapper1.queryUsers();
session1.close();//必须关闭sqlSession才可缓存数据
System.out.println("=============");
mapper2.deleteUserById(1);
session2.commit();//DML成功, 数据发生变化, 缓存清空
session2.close();
System.out.println("=============");
mapper3.queryUsers();
session3.close();//缓存未击中, 重新查询数据库, 重新缓存
}
引入Druid依赖
创建MyDruidDataSourceFactory类, 并继承PooledDataSourceFactory, 并替换数据源
package com.dz.datasource;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.datasource.pooled.PooledDataSourceFactory;
/**
mybatis-config.xml中连接池相关配置
注意: < property name="属性名" />属性名必须和com.alibaba.druid.pool.DruidAbstractDataSource中一致
pom.xml中引入PageHelper依赖
在mybatis-config.xml中添加 < plugins >
<plugins>
<!--com.github.pagehelper 为PageHelper类所在包名-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"/>
</plugins>
<environments></environments>
使用PageHelper提供的静态方法设置分页查询条件
@Test
public void testPage() {
//查询前, 设置分页, 查询第一页, 每页两条数据
//PageHelper 对其之后的第一个查询, 进行分页功能追加
PageHelper.startPage(1,2);
List
for (User user : users) {
System.out.println(user);
}
}
使用PageInfo保存分页查询结果
@Test
public void testPage() {
//查询前, 设置分页, 查询第一页, 每页两条数据
//PageHelper 对其之后的第一个查询, 进行分页功能追加
PageHelper.startPage(1,2);
List
for (User user : users) {
System.out.println(user);
}
//将查询结果 封装到 PageInfo 对象中
PageInfo
System.out.println("================");
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章