pom.xml
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.4version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.45version>
dependency>
定义核心配置文件 SqlMapConfig.xml
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///bank"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="UserMapper.xml"/>
mappers>
configuration>
定义 mapper 文件 UserMapper.xml
<mapper namespace="userMapper">
<select id="findAll" resultType="com.demo.pojo.User">
select * from user
select>
mapper>
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User{
private Integer id;
private String username;
private String password;
}
public interface UserMapper{
List<User> findAll();
}
public class UserMapperImpl implements UserMapper {
@Override
public List<User> findAll(){
// 读取核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
// 生成 sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// userMapper.findAll => namespace.id
List<User> userList = sqlSession.selectList("userMapper.findAll");
sqlSession.close();
return userList;
}
}
需要遵循以下规范:
<mapper namespace="com.demo.dao.UserMapper">mapper>
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.findAll();
<properties resource="jdbc.properties"/>
<property name="driver" value="${jdbc.driver}"/>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
<setting name="cacheEnabled" value="true"/>
settings>
<typeAliases>
<typeAlias type="com.demo.pojo.User" alias="user"/>
typeAliases>
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql"/>
plugin>
plugins>
<mappers>
<mapper resource="UserMapper.xml"/>
<package name="com.demo"/>
mappers>
<select id="findByCondition" parameterType="user" resultType="user">
select * from user
<where>
<if test="id!=0">
and id = #{id}
if>
<if test="username!=null">
and username = #{username}
if>
where>
select>
<select id="findByIds" parameterType="list" resultType="user">
select * from user
<where>
<foreach collection="list" open="id in (" close=")" item="id" separator=",">
#{id}
foreach>
where>
select>
List<Integer> list = Arrays.asList(1, 2, 3);
// SQL : select * from user WHERE id in ( ? , ? , ? )
List<User> userList = userMapper.findByIds(list);
<sql id="selectUser">select * from usersql>
<select id="findAll" resultType="user">
<include refid="selectUser">include>
select>
假定一个数据模型,订单——用户关系。
一个订单只能属于一个用户。站在订单的角度,所以接口需要在订单类中编写。
@Data
@AllArgsConstructor
@NoArgsConstructor
// 订单信息
public class Order {
private Integer id;
private String orderTime;
private Integer total;
// 一个订单只能属于一个用户 在订单dao中定义的
private User user;
}
<resultMap id="orderMap" type="com.demo.pojo.Order">
<result column="uid" property="user.id"/>
<result column="password" property="user.password"/>
<result column="username" property="user.username"/>
resultMap>
<select id="findAll" resultMap="orderMap">
select * from orders o,user u where o.uid = u.id
select>
也可以写成:
<resultMap id="orderMap" type="com.demo.pojo.Order">
<result property="id" column="id"/>
<result property="orderTime" column="order_time"/>
<result property="total" column="total"/>
<association property="user" javaType="user">
<result column="uid" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
association>
resultMap>
一个用户可以有多个订单。站在用户的角度,所以接口需要在用户类中编写。
private List<Order> orderList;
<resultMap id="userMap" type="com.demo.pojo.User">
<result column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<collection property="orderList" ofType="com.demo.pojo.Order">
<result column="oid" property="id"/>
<result column="total" property="total"/>
<result column="order_time" property="orderTime"/>
collection>
resultMap>
<select id="findWithOrders" resultMap="userMap">
select *,o.id oid from user u left join orders o on u.id=o.uid
select>
多对多 和 一对多 的原理一样。只是查询的时候需要定义一张中间表。
假定一个数据模型,角色——用户关系。一个用户可以有多个角色,一个角色可以属于多个用户。
此处我们站在用户的角度查询,这个用户有什么角色。
<resultMap id="userRoleMap" type="user">
<result column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<collection property="roleList" ofType="com.demo.pojo.Role">
<result column="rid" property="id"/>
<result column="role_name" property="roleName"/>
collection>
resultMap>
<select id="findWithRoles" resultMap="userRoleMap">
select u.*,r.*,r.id rid from user u left join user_role ur on u.id=ur.user_id inner join role r on ur.role_id=r.id
select>
简单注解:
@Insert("insert into user (id,username) values (#{id},#{username})")
int saveUser(User user);
@Update("update user set username = #{username} where id = #{id}")
void updateUser(User user);
@Delete("delete from user where id = #{id}")
void deleteUser(Integer id);
@Select("select * from user where id = #{id}")
User findUserById(Integer id);
// 根据 用户 id 查询角色
@Select("select * from role r,user_role ur where r.id=ur.role_id and ur.user_id = #{uid}")
List<Role> findByUid(Integer uid);
// 根据 用户 id 查询订单
@Select("select * from orders where uid = #{uid}")
List<Order> findByUid(Integer uid) throws Exception;
// 当前订单属于哪个用户 一对一
@Select("select * from orders")
@Results({
@Result(id = true, property = "id", column = "id"),
@Result(property = "orderTime", column = "order_time"),
@Result(property = "total", column = "total"),
@Result(property = "user", column = "uid", javaType = User.class,
one = @One(select = "com.demo.dao.UserMapper.findUserById"))
})
List<Order> findAll();
// 查询每个用户的订单 一个用户有多个订单 一对多
@Select("select * from user")
@Results({
@Result(id = true, property = "id", column = "id"),
@Result(property = "username", column = "username"),
@Result(property = "password", column = "password"),
@Result(property = "orderList", column = "id", javaType = List.class,
many = @Many(select = "com.demo.dao.OrderMapper.findByUid"))
})
List<User> findWithOrders();
// 查询每个用户的角色 一个用户可以有多个角色
@Select("select * from user")
@Results({
@Result(id = true, property = "id", column = "id"),
@Result(property = "username", column = "username"),
@Result(property = "password", column = "password"),
@Result(property = "roleList", column = "id", javaType = List.class,
many = @Many(select = "com.demo.dao.RoleMapper.findByUid"))
})
List<User> findWithRoles()
默认开启的。sqlSession 级别。
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 只打印一次 SQL
User user1 = userMapper.findUserById(1);
System.out.println(user1);
User user2 = userMapper.findUserById(1);
System.out.println(user2);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 中间穿插 更新操作 sqlSession.commit() 会清空缓存
User user1 = userMapper.findUserById(1);
System.out.println(user1);
User user = new User();
user.setId(3);
user.setUsername("zz");
userMapper.saveUser(user);
User user2 = userMapper.findUserById(1);
System.out.println(user2);
默认关闭。namespace 级别。
<settings>
<setting name="cacheEnabled" value="true"/>
settings>
<cache/>
// 创建 两个 sql session
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
User user1 = userMapper1.findUserById(1);
System.out.println(user1);
sqlSession1.close(); //第一次查询完后关闭sqlSession 只打印一次 SQL
User user2 = userMapper2.findUserById(1);
System.out.println(user2);
注解模式下开启二级缓存:
@CacheNamespace
public interface UserMapper{}
二级缓存整合reids。
<dependency>
<groupId>org.mybatis.cachesgroupId>
<artifactId>mybatis-redisartifactId>
<version>1.0.0-beta2version>
dependency>
# redis.properties
host=192.168.84.145
port=6379
connectionTimeout=5000
password=
database=1
<cache type="org.mybatis.caches.redis.RedisCache"/>
@CacheNamespace(implementation = RedisCache.class)
@Intercepts({
// 可以拦截的方法 Executor、StatementHandler、ParameterHandler、ResultSetHandler
@Signature(type = StatementHandler.class,
method = "prepare",
args = {Connection.class, Integer.class})
})
public class CustomPlugin implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("自定义插件...");
// 继续执行
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
System.out.println("将要包装的⽬标对象:" + target);
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
System.out.println("插件配置的初始化参数:" + properties);
}
}
<plugins>
<plugin interceptor="com.demo.plugins.CustomPlugin">
<property name="name" value="Hello Plugin"/>
plugin>
plugins>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>3.7.5version>
dependency>
<dependency>
<groupId>com.github.jsqlparsergroupId>
<artifactId>jsqlparserartifactId>
<version>0.9.1version>
dependency>
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql"/>
plugin>
@Test
public void testPageHelper() {
// 分页插件 会自动拼接上 limit
PageHelper.startPage(1, 1);
UserMapper userMapper = openSession().getMapper(UserMapper.class);
List<User> userList = userMapper.findAll();
System.out.println(userList);
PageInfo<User> pageInfo = new PageInfo<>(userList);
System.out.println(pageInfo);
}
<dependency>
<groupId>tk.mybatisgroupId>
<artifactId>mapperartifactId>
<version>3.1.2version>
dependency>
<plugin interceptor="tk.mybatis.mapper.mapperhelper.MapperInterceptor">
<property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>
plugin>
public interface UserMapper extends Mapper<User> {}
// 此处不用写 mapper接口能直接调用 select 方法
User user = new User();
user.setId(1);
List<User> select = userMapper.select(user);
// 根据条件查询
Example example = new Example(User.class);
example.createCriteria().andEqualTo("id", 1);
List<User> userList = userMapper.selectByExample(example);
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.1.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/bank?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false
username: root
password: 123456
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 驼峰命名自动转换
map-underscore-to-camel-case: true
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
// 主键自增策略
@TableId(type = IdType.AUTO)
private Integer id;
// 解决字段不一致问题
@TableField("username")
private String username;
// 该字段不加入查询 返回结果为 null
@TableField(select = false)
private String password;
@TableLogic
private Integer deleteFlag;
}
public interface UserMapper extends BaseMapper<User> {}
@Autowired
private UserMapper userMapper;
// springboot 启动类添加该注解 进行 mapper 接口扫描
@MapperScan("com.demo.mapper")
@Test
void testInsert() {
User user = new User();
user.setUsername("zz");
user.setPassword("123456");
int insert = userMapper.insert(user);
// 返回受影响行数
System.out.println(insert);
}
@Test
void testDeleteById() {
userMapper.deleteById(4);
}
@Test
void testDeleteByMap() {
Map<String, Object> columnMap = new HashMap<>();
columnMap.put("username", "zhangsan");
userMapper.deleteByMap(columnMap);
}
@Test
void testDeleteByWrapper() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("id", 4);
userMapper.delete(wrapper);
}
@Test
void testDeleteByBatchIds() {
userMapper.deleteBatchIds(Arrays.asList(2, 3, 4));
}
@Test
void testUpdateById() {
User user = new User();
user.setId(4);
user.setUsername("yy");
user.setPassword("123456");
userMapper.updateById(user);
}
@Test
void testUpdateByWrapper() {
User user = new User();
// 更新的字段
user.setPassword("666666");
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 条件字段
wrapper.eq("id", 4);
userMapper.update(user, wrapper);
}
@Test
void testSelectById() {
// 根据ID查询
User user = userMapper.selectById(1);
System.out.println(user);
}
@Test
void testSelectByBatchIds() {
// select in
List<User> userList = userMapper.selectBatchIds(Arrays.asList(1, 3, 4));
System.out.println(userList);
}
@Test
void testSelectOne() {
// 根据条件查询
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("id", 1);
User user = userMapper.selectOne(wrapper);
System.out.println(user);
}
@Test
void testSelectCount() {
// 统计条目数
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("id", 1);
Integer count = userMapper.selectCount(wrapper);
System.out.println(count);
}
@Configuration
public class MybatisConfig {
// 分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
@Test
void testSelectPage() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("id", 1);
Page<User> page = new Page<>(1, 1);
IPage<User> userIPage = userMapper.selectPage(page, wrapper);
List<User> records = userIPage.getRecords();
System.out.println(records);
}
@Test
void testSelectList() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 基本比较符
wrapper.eq("id", 1); // id = 1
wrapper.ne("id", 1); // id != 1
wrapper.gt("id", 1); // id > 1
wrapper.ge("id", 1); // id >= 1
wrapper.lt("id", 1); // id < 1
wrapper.le("id", 1); // id <= 1
wrapper.between("id", 1, 4); // 1 <= id <=4
wrapper.notBetween("id", 1, 4); // id < 1 && id > 4
wrapper.in("id", "1", "2", "3");
wrapper.notIn("id", "2", "3");
// 模糊查询
wrapper.like("username", "z"); // %z%
wrapper.notLike("username", "z"); // not like %z%
wrapper.likeLeft("username", "z"); // %z
wrapper.likeRight("username", "z"); // z%
// 排序
wrapper.orderByAsc("id", "username");
wrapper.orderByDesc("id", "username");
// or & and
wrapper.eq("id", 1).or().eq("id", 2);
// 默认查询所有字段 指定查询字段
wrapper.select("id", "username");
List<User> userList = userMapper.selectList(wrapper);
System.out.println(userList);
}
public class FindAll extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
String sqlMethod = "findAll";
String sql = "select * from " + tableInfo.getTableName();
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return addSelectMappedStatement(mapperClass, sqlMethod, sqlSource, modelClass, tableInfo);
}
}
public class CustomSqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList() {
List<AbstractMethod> methodList = super.getMethodList();
methodList.add(new FindAll());
return methodList;
}
}
// springboot 配置类添加自定义配置
@Bean
public CustomSqlInjector customSqlInjector() {
return new CustomSqlInjector();
}
// 将自定义的 mapper 类继承 BaseMapper 进行扩展
public interface CustomBaseMapper<T> extends BaseMapper<T> {
List<T> findAll();
}
public interface UserMapper extends CustomBaseMapper<User> {}
@Test
void testCustomFindAll(){
List<User> all = userMapper.findAll();
System.out.println(all);
}
// 在实体类中定义逻辑删除字段
@TableLogic
private Integer deleteFlag;
mybatis-plus:
global-config:
db-config:
# 逻辑已删除值(默认为 1)
logic-delete-value: 1
# 逻辑未删除值(默认为 0)
logic-not-delete-value: 0
参考git:https://gitee.com/zhangyizhou/learning-mybatis-demo.git