【MyBatis】MyBatis 注解开发
MyBatis 注解开发
环境搭建
Mybatis 也可以使用注解开发方式,这样就可以减少编写 Mapper 映射文件。
常用注解说明:
@Insert实现新增@Update实现更新@Delete实现删除@Select实现查询@Result实现结果集封装@Results可以与@Result一起使用,封装多个结果集@ResultMap实现引用@Results定义的封装@One实现一对一结果集封装@Many实现一对多结果集封装@SelectProvider实现动态 SQL 映射@CacheNamespace实现注解二级缓存的使用
单表 CRUD
实现复杂关系映射之前可以在映射文件中通过配置 <resultMap> 来实现,在使用注解开发时需要借助 @Results 注解,@Result 注解,@One 注解,@Many 注解。
@Results代替了<id>标签和<result>标签,属性介绍:- id 是否是主键字段
- column 数据库的列名
- property 需要装配的属性名
- one 需要使用的 @One 注解
@Result(one=@One)() - many 需要使用的 @Many 注解(
@Result(many=@Many)()
@One(一对一) 代替了<assocation>标签,是多表查询的关键,在注解中用来指定子查询返回单一对象,属性介绍:- select 指定用来多表查询的 sqlmapper
- fetchType 会覆盖全局的配置参数 lazyLoadingEnabled
- 使用格式:
@Result(column=" ", property="", one=@One(select=""))
@Many(多对一)代替了<collection>标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合,- 使用格式:
@Result(property="", column="", many=@Many(select=""))
- 使用格式:
编写实体类
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
}
使用注解方式开发持久层接口
package cn.parzulpan.dao; import cn.parzulpan.domain.User;
import org.apache.ibatis.annotations.*; import java.util.List; /**
* @Author : parzulpan
* @Time : 2020-12
* @Desc : 用户的持久层接口,使用注解开发
*/ public interface UserDAO { /**
* 查询所有用户
* @return
*/
@Select("select * from user")
@Results(id = "userMap",
value = {
@Result(id = true, column = "id", property = "userId"),
@Result(column = "username", property = "userName"),
@Result(column = "birthday", property = "userBirthday"),
@Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress")
})
List<User> findAll(); /**
* 根据 id 查询一个用户
* @param userId
* @return
*/
@Select("select * from user where id = #{uid}")
@ResultMap(value = {"userMap"})
User findById(Integer userId); /**
* 插入操作
* @param user
* @return
*/
@Insert("insert into user(username, birthday, sex, address) values (#{userName}, #{userBirthday}, #{userSex}, #{userAddress})")
@SelectKey(keyColumn = "id", keyProperty = "userId", resultType = Integer.class, before = false,
statement = {"select last_insert_id()"})
int saveUser(User user); /**
* 更新操作
* @param user
* @return
*/
@Update("update user set username = #{userName}, birthday = #{userBirthday}, sex = #{userSex}, " +
"address = #{userAddress} where id = #{userId}")
int updateUser(User user); /**
* 删除操作
* @param userId
* @return
*/
@Delete("delete from user where id = #{uid}")
int deleteUser(Integer userId); /**
* 使用聚合函数查询
* @return
*/
@Select("select count(*) from user")
int findTotal(); /**
*
* @param name
* @return
*/
@Select("select * from user where username like #{username}")
@ResultMap(value = {"userMap"})
List<User> findByName(String name); }
编写 SqlMapConfig 配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mabatis.org//DTD Congfig 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration>
<!-- 配置 properties 文件的位置 -->
<properties resource="JDBCConfig.properties"/> <!-- 配置别名 -->
<typeAliases>
<package name="cn.parzulpan.domain"/>
</typeAliases> <!-- 配置 MySQL 环境 -->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<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> <!-- 配置映射信息 -->
<mappers>
<package name="cn.parzulpan.dao"/>
</mappers>
</configuration>
编写测试方法
package cn.parzulpan; import cn.parzulpan.dao.UserDAO;
import cn.parzulpan.domain.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 org.junit.After;
import org.junit.Before;
import org.junit.Test; import java.io.InputStream;
import java.util.Date;
import java.util.List; /**
* @Author : parzulpan
* @Time : 2020-12
* @Desc :
*/ public class MyBatisAnnotationCRUDTest {
private InputStream is;
private SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
private SqlSessionFactory sqlSessionFactory;
private SqlSession sqlSession;
private UserDAO userDAO; @Before
public void init() throws Exception {
System.out.println("Before...");
is = Resources.getResourceAsStream("SqlMapConfig.xml");
sqlSessionFactory = builder.build(is);
sqlSession = sqlSessionFactory.openSession();
userDAO = sqlSession.getMapper(UserDAO.class);
} @After
public void destroy() throws Exception {
System.out.println("After...");
sqlSession.commit();
sqlSession.close();
is.close();
} @Test
public void findAllTest() {
List<User> users = userDAO.findAll();
for (User user : users) {
System.out.println(user);
}
} @Test
public void findByIdTest() {
User user = userDAO.findById(41);
System.out.println(user);
} @Test
public void saveUserTest() {
User user = new User(null, "annotation username", new Date(), "男", "Beijing");
System.out.println("save before: " + user); // User{id=null, ...}
int i = userDAO.saveUser(user);
System.out.println(i);
System.out.println("save after: " + user); // User{id=53, ...}
} @Test
public void updateUserTest() {
User user = userDAO.findById(42);
user.setUserName("Tom Tim Tom AA");
user.setUserAddress("瑞典");
int i = userDAO.updateUser(user);
System.out.println(i);
} @Test
public void deleteUserTest() {
int i = userDAO.deleteUser(53);
System.out.println(i);
} @Test
public void findTotalTest() {
int total = userDAO.findTotal();
System.out.println(total);
} @Test
public void findByNameTest() {
List<User> users = userDAO.findByName("%Tim%");
for (User user : users) {
System.out.println(user);
}
}
}
多表查询
一对一
需求:加载账户信息时并且加载该账户的用户信息,根据情况可实现延迟加载。
添加 User 实体类及 Account 实体类
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money; private User user; // 一对一
}
添加账户的持久层接口并使用注解配置
package cn.parzulpan.dao; import cn.parzulpan.domain.Account;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType; import java.util.List; /**
* @Author : parzulpan
* @Time : 2020-12
* @Desc :
*/ public interface AccountDAO { /**
* 查询所有账户,采用延迟加载的方式查询账户的所属用户
* @return
*/
@Select("select * from account")
@Results(id = "accountMap", value = {
@Result(id = true, column = "id", property = "id"),
@Result(column = "uid", property = "uid"),
@Result(column = "money", property = "money"),
@Result(column = "uid", property = "user", one = @One(select = "cn.parzulpan.dao.UserDAO.findById", fetchType = FetchType.LAZY))
})
List<Account> findAll();
}测试一对一关联及延迟加载
@Test
public void findAllTest() {
List<Account> accounts = accountDAO.findAll();
for (Account account : accounts) {
System.out.println();
System.out.println(account);
System.out.println(account.getUser());
}
}
``
一对多
需求:查询用户信息时,也要查询他的账户列表。使用注解方式实现。
User 实体类加入
List<Account>public class User implements Serializable {
private Integer userId; // 注意这里的和数据库表的列名不一致
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress; private List<Account> accounts; //一对多关系映射:主表方法应该包含一个从表方的集合引用
}
编写用户的持久层接口并使用注解配置
public interface UserDAO {
/**
* 查询所有用户,包括账户列表
* @return
*/
@Select("select * from user")
@Results(id = "userMapWithAccount",
value = {
@Result(id = true, column = "id", property = "userId"),
@Result(column = "username", property = "userName"),
@Result(column = "birthday", property = "userBirthday"),
@Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress"),
@Result(column = "id", property = "accounts", many = @Many(
select = "cn.parzulpan.dao.AccountDAO.findByUid",
fetchType = FetchType.LAZY
))
})
List<User> findAllWithAccount();
}
编写账户的持久层接口并使用注解配置
public interface AccountDAO { /**
* 根据用户 id 查询用户下的所有账户
* @param userId
* @return
*/
@Select("select * from account where uid = #{uid} ")
List<Account> findByUid(Integer userId);
}
添加测试方法
package cn.parzulpan; import cn.parzulpan.dao.UserDAO;
import cn.parzulpan.domain.Account;
import cn.parzulpan.domain.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 org.junit.After;
import org.junit.Before;
import org.junit.Test; import java.io.InputStream;
import java.util.List; /**
* @Author : parzulpan
* @Time : 2020-12
* @Desc :
*/ public class MyBatisAccountManyTest {
private InputStream is;
private SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
private SqlSessionFactory sqlSessionFactory;
private SqlSession sqlSession;
private UserDAO userDAO; @Before
public void init() throws Exception {
System.out.println("Before...");
is = Resources.getResourceAsStream("SqlMapConfig.xml");
sqlSessionFactory = builder.build(is);
sqlSession = sqlSessionFactory.openSession();
userDAO = sqlSession.getMapper(UserDAO.class);
} @After
public void destroy() throws Exception {
System.out.println("After...");
sqlSession.commit();
sqlSession.close();
is.close();
} @Test
public void findAllWithAccountTest() {
List<User> users = userDAO.findAllWithAccount();
for (User user : users) {
System.out.println();
System.out.println(user);
System.out.println(user.getAccounts());
}
}
}
缓存配置
在 SqlMapConfig 中开启二级缓存支持
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mabatis.org//DTD Congfig 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration>
<!-- 配置二级缓存 -->
<settings>
<!-- 开启二级缓存的支持 -->
<setting name="cacheEnabled" value="true"/>
</settings>
</configuration>
在持久层接口中使用注解配置二级缓存
@CacheNamespace(blocking = true) // 基于注解方式实现配置二级缓存
public interface UserDAO {
}
测试
@Test
public void findByIdHighCacheTest() {
SqlSession sqlSession1 = sqlSessionFactory.openSession();
UserDAO dao1 = sqlSession1.getMapper(UserDAO.class);
User user1 = dao1.findById(41);
System.out.println(user1.hashCode()); // 765284253
sqlSession1.close(); // 一级缓存消失 SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserDAO dao2 = sqlSession2.getMapper(UserDAO.class);
User user2 = dao2.findById(41);
System.out.println(user2.hashCode()); // 1043351526
sqlSession1.close(); // 一级缓存消失 System.out.println(user1 == user2); // false }
练习和总结
【MyBatis】MyBatis 注解开发的更多相关文章
- spring boot整合mybatis基于注解开发以及动态sql的使用
让我们回忆一下上篇博客中mybatis是怎样发挥它的作用的,主要是三类文件,第一mapper接口,第二xml文件,第三全局配置文件(application.properties),而今天我们就是来简化 ...
- mybatis的注解开发之三种动态sql
脚本sql XML配置方式的动态SQL我就不讲了,有兴趣可以自己了解,下面是用<script>的方式把它照搬过来,用注解来实现.适用于xml配置转换到注解配置 @Select(" ...
- mybatis学习:mybatis的注解开发和编写dao实现类的方式入门
一.使用注解则不需要创建映射配置文件:即xxxDao.xml javaBean为什么要实现Serializable接口? Java的"对象序列化"能让你将一个实现了Serializ ...
- Mybatis使用注解开发(未完)
使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心 注解在接口实现 @Select("SELECT * FROM user") Lis ...
- MyBatis使用注解开发
- mybatis学习:mybatis的注解开发CRUD操作
Dao层: public interface IUserDao { /** * 查询所有结果 * @return */ @Select("select * from user") ...
- Mybatis注解开发模糊查询
Mybatis注解开发模糊查询 一般在使用mybatis时都是采用xml文件保存sql语句 这篇文章讲一下在使用mybatis的注解开发时,如何进行模糊查询 模糊查询语句写法(在@Select注解中) ...
- 学习MyBatis必知必会(7)~注解开发、动态SQL
一.MyBatis的注解开发 开发中推荐是使用xml文件配置 1.配置映射关系[使用注解的方式]: <!-- 全局的配置文件 --> <configuration> <! ...
- Spring+SpringMVC+MyBatis深入学习及搭建(十六)——SpringMVC注解开发(高级篇)
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7085268.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十五)——S ...
- mybatis多参数传递,延迟加载,缓存,注解开发
1.Mybatis的多参数传递方式 需求:更具id 和 名字查询用户: select * from user where id = ? and name = ?: 1):QueryVo 或者 User ...
随机推荐
- ajax的五种状态
ajax的五种状态(readyState ) 0 - (未初始化)还没有调用send()方法 1 - (载入)已调用send()方法,正在发送请求 2 - (载入完成)send()方法执行完成,已经接 ...
- SNOI2020 部分题解
D1T1 画图可以发现,多了一条边过后的图是串并联图.(暂时不确定) 然后我们考虑把问题变成,若生成树包含一条边\(e\),则使生成树权值乘上\(a_e\),否则乘上\(b_e\),求最终的生成树权值 ...
- BJWC2011 禁忌
题目链接 题解 多模式匹配首先建 AC 自动机,看到 \(len \le 10^9\) 想到矩阵乘法优化. 朴素 DP 关于分割的最大值,可以贪心,只要走到一个能匹配串的点立刻返回根继续匹配就行,一定 ...
- git学习——git命令之创建版本库和版本退回
原文来至 一.创建版本库 版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改.删除,Git都能跟踪,以便任何时刻都可以追 ...
- 服务器ganglia安装(带有登录验证)
1.ganglia组件gmond相当于agent端,主要手机各node的性能状态:gmetad相当于server端,从gmond以poll的方式收集和存储原数据:ganglia-web相当于一个web ...
- 【Django】django.core.exceptions.ImproperlyConfigured: mysqlclient 1.4.0 or newer is required;
报错信息 django.core.exceptions.ImproperlyConfigured: mysqlclient 1.4.0 or newer is required; you have 0 ...
- 浅谈JAVA代码优化
JAVA代码的优化分为两个方面: 一.减小代码的体积.二.提高代码的执行效率. ============================================================ ...
- xss靶场练习(7.22)
靶场地址:http://xss.fbisb.com/ 参考的文章:https://www.cnblogs.com/cute-puli/p/10834954.html 感谢大佬的分享 做这个题的思路就 ...
- [BUUCTF] 真的很杂
这似乎是一道安卓逆向题??我就是没有搞懂安卓逆向原来是misc吗... 安卓逆向一个例子 工具准备 1.apktool--可以反编译软件的布局文件.图片等资源,方便大家学习一些很好的布局: 2.dex ...
- RabbitMq基本概念理解
RabbitMQ的基本概念 RabbitMQ github项目地址 RabbitMQ 2007年发布,是一个在AMQP(高级消息队列协议)基础上完成的,可复用的企业消息系统,是当前最主流的 消息中间件 ...