「转载」原文链接请点击
基本应用
1.快速入门
1.1.官网 :www.mybatis.org/mybatis-3/
1.2.开发步骤
1.2.1.添加Mybatis的坐标(添加pom.xml依赖)
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--日志-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
1.2.2.创建user数据表
...
1.2.3.编写user实体
...
1.2.4.编写映射文件UserMapper.xml与标签说明
<!--
<?xml ...> 映射文件DTD约束头
<mapper> 根标签
namespae 命名空间,与语句ID标识id组成查询的标识
<select> 查询操作
<update> 更新操作
<insert> 添加操作
<delete> 删除操作
id 语句ID标识,与命名空间一起组织成查询标识
resultType 查询结果对应的实体类型
parameterType 查询对象类型
-->
<?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">
<mapper namespace="UserMapper">
<select id="find" resultType="com.otoom.pojo.User" parameterType="com.otoom.pojo.User">
select * from User WHERE username = #{username}
</select>
</mapper>
1.2.5.编写核心文件SqlMapConfig.xml
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN“ "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<!--环境,默认环境为:development-->
<environments default="development">
<!--环境配置-->
<environment id="development">
<!--当前事务交给JDBC处理-->
<transactionManager type="JDBC"/>
<!--使用mybatis提供的连接池-->
<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>
<!--使用指定文件路径
<mapper resource="com/xxx/mapper/UserMapper.xml"/>
-->
<!--
指定包名,会扫描这个文件夹下所有的xml
这个xml的路径包名在resource中,需要和接口的包名一致
如: resources目录下:com/xxx/mapper 存放xml文件
-->
<package name="com.xxx.mapper"/>
</mappers>
</configuration>
1.2.6.使用
public static void main(String[] args){
//获取配置信息
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//获取工厂类
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(resourceAsStream);
//开启sql会话
SqlSession sqlSession = sqlSessionFactory.openSession();
//开始执行对应操作
User query = new User();
query.setUsername("Tom");
int insert = sqlSession.insert("userMapper.find", query);
//提交事务
//sqlSession.commit(); //CUD操作需要提交事务
//关闭会话
sqlSession.close();
}
1.2.7.sqlConfig.xml核心配置文件标签说明
environments
数据库环境的配置,支持多环境配置
environment
环境变量
transactionManager
事务管理器,有两种类型:
1. JDBC:使用了JDBC的提交和回滚设置,依赖于从数据源得到的链接来管理事务作用域
2. MANAGED:这个配置几乎什么都没有做,它从不提交和回滚一个链接,而是让容器去管理事务的整个生命周期。默认情况下它会关闭连接,然后有些容器不希望关闭,所以需要将 closeConnection 属性设置为false来阻止它的默认行为
dataSource
数据源,有三种类型:
1. UNPOOLED:非连接池类型。这个数据源实现只是每次请求时打开和关闭连接
2. POOLED:连接池类型。这种数据源实现利用"池"的概念将JDBC连接对象组织起来
3. JNDI:这个数据源实现是为了能在如EJB或者应用服务器这类的容器中使用,容器可以集中或在外部配置数据源,然后放置一个JNDI上下文引用
property
属性
propertys
属性,该标签可以加载额外配置的properties文件,如resource文件夹下的jdbc.properties。使用方式为:${jdbc.driver} 可以引用对应的值
mappers
映射器,作用是加载sql的映射:
1. 使用相对于类路径:
```xml
<mapper resource="com/xxx/mapper/UserDao.xml"/>
```
2. 使用完全限定资源定位符(URL):
```xml
<mapper url="file:///user/xx/project/xxx/UserDao.xml"/>
```
3. 使用映射器接口实现类的完全限定类名:
```xml
<mapper class="com.xxx.UserDao"/>
```
4. 使用包内的映射器接口实现全部注册为映射器:
xml存放的包名,需要和接口存在的报名保持一致,如resources目录下,有包 com.xxx.mapper,所有xml文件需要存放到这个目录下
```xml
<package name="com.xxx.mapper"/>
```
2.复杂映射开发
2.1.准备
- 实体(对应数据库表)
public class User{
private Integer id;
private String userName;
//一个用户,有多个订单(一对多)
private List<Order> orderList;
//用户角色(多对多)
private List<Role> roleList;
}
public class Order{
private Integer id;
private Integer userId;
private String orderTime;
//一个订单,只有一个用户(一对一)
private User user;
}
public class Role{
private Integer id;
private String roleName;
}
public class UserRole{
private Integer userId
private Integer roleid;
}
- Mapper接口
public class OrderMapper{
List<Order> findAll();
//查询一对一
List<Order> finUserAndOrder();
}
public class UserMapper{
User findById(Integer userId);
//查询一对多
List<User> findAll();
//查询多对对
List<User> findAllUserAndRole();
}
public class RoleMapper{
//查询多对对
List<Role> findByUserId(Integer userId);
}
2.2.一对一查询
OrderMapper.xml编写
<mapper namespace="OrderMapper">
<!--一对一映射配置-->
<resultMap id="orderMap" type="Order">
<result property="id" column="id"/>
<result property="userId" column="userId"/>
<result property="orderTime" column="orderTime"/>
<!--
这里配置User对象里面的user属性的User对象与表字段的映射关系
实现把user和order的一对一关系映射
-->
<association property="user" javaType="User">
<result property="id" column="userId"/>
<result property="username" column="username"/>
</association>
</resultMap>
<!--
resultMap: 手动配置实体属性与表字段的映射关系
-->
<select id="finUserAndOrder" parameterType="Order" resultMap="orderMap">
select * from order o,user u where o.userId = u.id
</select>
</mapper>
###2.3.一对多查询
从用户角度出发,查询一对多结果;
UserMapper.xml的编写
<mapper namespace="UserMapper">
<!--一对多映射配置-->
<resultMap id="userMap" type="User">
<result property="id" column="id"/>
<result property="username" column="username"/>
<!--
这里配置orderList属性的Order对象与表字段的映射关系
-->
<collection property="orderList" ofType="Order">
<result property="id" column="oid"/>
<result property="userId" column="userId"/>
<result property="orderTime" column="orderTime"/>
</collection>
</resultMap>
<!--
resultMap: 手动配置实体属性与表字段的映射关系
-->
<select id="findAll" parameterType="User" resultMap="userMap">
select *,o.id oid from user u left join order o on o.userId = u.id
</select>
</mapper>
2.4.多对多查询
用户和角色的关系,就是多对多查询;
UserMapper.xml
<mapper namespace="UserMapper">
<!--一对多映射配置-->
...
<!--多对多映射配置-->
<resultMap id="userRoleMap" type="User">
<result property="id" column="id"/>
<result property="username" column="username"/>
<!--
这里配置roleList属性的Role对象与表字段的映射关系
-->
<collection property="roleList" ofType="Role">
<result property="id" column="rid"/>
<result property="roleName" column="roleName"/>
</collection>
</resultMap>
<select id="findAllUserAndRole" parameterType="User" resultMap="userRoleMap">
select u.*,r.*,r.id rid from user u
left join user_role ur on u.id = ur.userId
left join role r on r.id = ur.roleId
</select>
</mapper>
2.5.测试复杂映射
public static void main(String[] args){
//获取配置输入流
InputStream inputStream = Resources.getResourceAsSteam("splMapConfig.xml");
//获取sql会话
SqlSession sqlSession = SqlSessionFactoryBuilder.build(inputStream).openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//执行查询
/*
一对一
*/
List<Order> orderList = orderMapper.finUserAndOrder();
for(Order order : orderList){
System.out.println(order)
}
/*
一对多
*/
List<User> userList = userMapper.findAll();
for(User user : userList){
System.out.println(user)
}
/*
多对多
*/
List<User> userList = userMapper.findAllUserAndRole();
for(User user : userList){
System.out.println(user)
}
sqlSession.close();
}
3.Mybatis注解开发
3.1.常用注解
-
@Insert 新增
-
@Update 更新
-
@Delete 删除
-
@Select 查询
-
@Result 实现结果集封装
代替了xml中的和标签
有以下属性:
- column 数据库的字段名
- property 对应对象的属性名
- one 需要使用的@One注解 :@Result( one=@One )
- many 需要使用@Many注解:@Result( many=@Many )
-
@Results 可以与@Result一起使用,封装多个结果集
代替了xml中的标签,也可以使用@Result集合,使用格式:
@Results({ @Result(),@Result() }) -
@One 一对一结果集封装
代替了标签,是多表查询的关键,在注解中用来指定子查询返回单一对象
有以下属性:
-
select 指定用来多表查询的 sqlmapper
@Result(column="",property="",one=@One(select=""))
-
-
@Many 一对多结果集封装
代替了标签,是多表查询的关键,再注解中用来指定子查询返回的对象集合
-
有以下属性:
-
select 指定用来多表查询的 sqlmapper
@Result(column="",property="",one=@Many(select=""))
-
-
3.2.使用注解开发
3.2.1.一对一查询
public class OrderMapper{
//查询一对一
@Select("select * from order")
@Results({
@Result(id=true,property="id",column="id"),
@Result(property="userId",column="userId"),
@Result(property="orderTime",column="orderTime")
@Result(property="user",column="userId",
javaType=User.class,
one=@One(select="com.xxx.mapper.UserMapper.findById")
)
})
List<Order> finUserAndOrder();
...
}
public class UserMapper{
@Select("select * from user where id=#{userId}")
User findById(Integer userId);
...
}
3.2.2.一对多查询
public class OrderMapper{
@Select("select * from order where userId=#{userId}")
List<Order> findByUserId(Integer userId);
...
}
public class UserMapper{
//查询一对多
@Select("select * from user")
@Results({
@Result(id=true,property="id",column="id"),
@Result(id=true,property="username",column="username"),
@Result(property="orderList",column="id",
javaType=List.class,
many=@Many(select="com.xxx.mapper.OrderMapper.findByUserId")
})
List<User> findAllUserAndOrder();
...
}
3.2.3.多堆多查询
public class UserMapper{
//查询多对对
@Select("select * from user")
@Results({
@Result(id=true,property="id",column="id"),
@Result(property="username",column="username"),
@Result(property="roleList",column="id",
javaType=List.class,
many=@Many(select="com.xxx.mapper.RoleMapper.findByUserId"))
})
List<User> findAllUserAndRole();
}
public class RoleMapper{
//查询多对对
@Select("select * from role r,user_role ur where r.id=ur.roleId and ur.userId = #{userId}")
List<Role> findByUserId(Integer userId);
}
4.一级缓存
-
什么是一级缓存?
-
为什么使用一级缓存?
Mybatis会在会话对象SqlSession对象中建议一个简单的缓存,将查询到的结果缓存起来,当下次查询的时候,会判断有没有一个完全一样的查询,如果有直接从缓存中返回。否则查询数据库并存入缓存,最后返回给用户。
这样做,是避免我们在短时间内,反复的执行相同的查询语句,而得到的结果也是相同的。这样会造成很大的资源浪费。
4.1.一级缓存的原理及源码分析
-
底层是使用HashMap的数据结构存储
-
缓存是在执行器Executor中创建,添加和删除缓存都在这里执行
-
默认的缓存Key有五个部分组成(具体可以查看类:BaseExecutor):
-
statementId:MapStatement的id
-
offset:分页设置,默认为0,从RowBound分页对象中获取
-
limit:分页最大页数,从RowBound分页对象中获取
-
boundSql:查询的sql语句,从BoundSql对象中获取
-
value:sql的参数,parameter中获取
-
env: 当前的环境,如果sqlMapConfig.xml有配置
<environment id="development">, 也会设置到key中
相关源码:
CacheKey cacheKey = new CacheKey(); //MappedStatement 的 id // id就是Sql语句的所在位置包名+类名+ SQL名称 cacheKey.update(ms.getId()); // offset 就是 0 cacheKey.update(rowBounds.getOffset()); // limit 就是 Integer.MAXVALUE cacheKey.update(rowBounds.getLimit()); //具体的SQL语句 cacheKey.update(boundSql.getSql()); //后面是update 了 sql中带的参数 cacheKey.update(value); ... if (configuration.getEnvironment() != null) { // issue #176 cacheKey.update(configuration.getEnvironment().getId()); } -
-
BaseExecutor部分query源码:
@Override public <E> List<E> query(MappedStatement ms, Object parameter,RowBounds rowBounds,ResultHandler resultHandler) throws SQLException { //如果查不到的话,就从数据库查,在queryFromDatabase中,会对localcache进行写入。 localcache对象的put方法最终交给Map进行存放 BoundSql boundSql = ms.getBoundSql(parameter); //创建缓存 CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql); return query(ms, parameter, rowBounds, resultHandler, key, boundSql); } @SuppressWarnings("unchecked") @Override public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException{ ... list = resultHandler == null ? (List<E>) localCache.getObject(key) : null; if (list != null) { //这个主要是处理存储过程用的。 handleLocallyCachedOutputParameters(ms, key, parameter, boundSql); } else { //从数据库中查询 list = queryFromDatabase(ms, parameter,rowBounds,resultHandler,key,boundSql); } ... } /** * queryFromDatabase 方法 */ private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { List<E> list; localCache.putObject(key, EXECUTION_PLACEHOLDER); try { //执行查询 list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql); } finally { //清除缓存中的数据 localCache.removeObject(key); } //把查询到的数据,重新放入一级缓存中 localCache.putObject(key, list); if (ms.getStatementType() == StatementType.CALLABLE) { localOutputParameterCache.putObject(key, parameter); } return list; }
4.2.二级缓存
-
什么是二级缓存?
-
二级缓存的作用?
-
二级缓存是怎么实现的?
- 二级缓存的原理和一级缓存原理一样,第一次查询,会将数据放入缓存中,然后第二次查询则会直接去
缓存中取
-
二级缓存需要手工开启,不像一级缓存一样默认就开启了。
-
二级缓存存储的不是对象,而是对象的数据;
-
对象需要实现Serializable接口,因为二级缓存的存放介质很多,可以是内存,磁盘等。所以在取数据的时候,就需要反序列化操作。
-
二级缓存是基于mapper文件的namespace。多个sqlSession可以共享一个mapper中的二级缓存区域
4.2.1.开启二级缓存
-
xml方式开启
-
在全局配置文件sqlMapConfig.xml添加以下配置:
<!--开启二级缓存--> <settings> <setting name="cacheEnabled" value="true"/> </settings> -
在Mapper.xml中添加配置:
<!--开启二级缓存--> <cache></cache>
-
-
注解开启
- 在Mapper类中添加注解:
//使用二级缓存,等用于<cache>属性 @CacheNamespace public interface UserMapper{ ... }
4.2.2.用Redis实现二级缓存
- 使用默认的二级缓存实现有哪些弊端?
- 使用缓存中间件实现二级缓存解决了哪些问题?
使用默认的二级缓存实现,只能在单机系统中使用,不能实现分布式缓存。
引入缓存中间件redis作为二级缓存的存储介质,可以实现多机分布式缓存数据存储,对缓存数据进行集中管理
-
添加依赖。在pom.xml中添加以下依赖:
<dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-redis</artifactId> <version>1.0.0-beta2</version> </dependency> -
在resources目录中添加配置 redis.properties
redis.host=localhost redis.port=6379 redis.connectionTimeout=5000 redis.password= redis.database=0默认情况下,如果是本地的redis,且没有其他特殊配置,mybatis-redis已经有默认的配置,不配置redis.properties也是可以的
-
指定使用RedisCache作为二级缓存
-
xml方式。在mapper.xml中,添加以下配置:
<cache type="org.mybatis.caches.redis.RedisCache" /> -
注解方式。使用implementation指定使用RedisCache
@CacheNamespace(implementation=RedisCache.class) public interface UserMapper{ ... }
-
4.2.3.RedisCache源码分析
-
如何实现的?
-
如何进行缓存的存取的?
-
用到的是什么数据结构?
- 实现了Mybatis的Cache接口
- 内部使用jdis封装了对redis的CURD操作
- 使用了redis的Hash数据结构,系列化后存储数据
- RedisCache在mybatis启动的时候,由MyBatis的CacheBuilder创建
RedisCache部分源码:
public final class RedisCache implements Cache {
public RedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require anID");
}
this.id = id;
//调用RedisConfigurationBuilder创建RedisConfig
RedisConfig redisConfig = RedisConfigurationBuilder.getInstance()
//RedisConfig核心方法,这个是加载解析redis配置文件的
.parseConfiguration();
pool = new JedisPool(redisConfig,redisConfig.getHost(),redisConfig.getPort(),redisConfig.getConnectionTimeout(),redisConfig.getSoTimeout(), redisConfig.getPassword(), redisConfig.getDatabase(), redisConfig.getClientName());
}
...
}
/**
* 通过类加载器加载redis配置资源,
*/
public RedisConfig parseConfiguration(ClassLoader classLoader) {
Properties config = new Properties();
InputStream input = classLoader.getResourceAsStream(redisPropertiesFilename);
if (input != null) {
try {
//加载配置信息到Properties容器中
config.load(input);
}catch (IOException e) {
throw new RuntimeException( "An error occurred while reading classpath property '" + redisPropertiesFilename + "', see nested exceptions", e);
} finally {
try {
input.close();
} catch (IOException e) {
// close quietly
}
}
}
//redisConfig继承了 JedisPoolConfig
RedisConfig jedisConfig = new RedisConfig();
//开始设置redis配置
setConfigProperties(config, jedisConfig);
return jedisConfig;
}
##5.Mybatis插件机制
-
使用插件有哪些好处?
-
Mybatis有哪4大组件?
-
Mybatis的四大组件有提供给了哪些拦截方法?
使用插件的好处:
-
是增加了框架的灵活性
-
开发者可以结合实际需求,对框架进行拓展,使其能够更好的工作
5.1. Mybatis的四大组件
-
实际就是拦截器
-
使用了动态代理的方式实现,4大组件都是代理对象
5.1.1.Executor组件
执行器Executor。提供了以下主要函数:
-
update
- query
- commit
- rollback
5.1.2.StatementHandler组件
SQL语法构建器StatementHandler。提供了以下主要函数:
- parameterize
- batch
- updates
- query
5.1.3.ParameterHandler组件
参数处理器ParameterHandler 。提供了以下主要函数:
- getParameterObject
- setParameters
5.1.4.ResultSeetHandler组件
结果集处理器ResultSetHandler 。提供了一下主要函数:
- handleResultSets
- handleOutputParameters
5.2.Mybatis的插件原理
-
通过动态代理
-
每次四大对象创建的时候,会通过InterceptorChain.pluginAll函数返回一个代理
-
ParameterHandler的源码示例:
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object object, BoundSql sql, InterceptorChain interceptorChain){
ParameterHandler parameterHandler =
mappedStatement.getLang().createParameterHandler(mappedStatement,object,sql);
//为目标对象生成代理,之后目标对象调用方法的时候走的不是原方法而是代理方法
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
}
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors){
target = interceptor.plugin(target);
}
return target;
}
interceptorChain保存了所有的拦截器(interceptors),是mybatis初始化的时候创建的。
调用拦截器链中的拦截器依次的对目标进行拦截或增强。
interceptor.plugin(target)中的target就可以理解为mybatis中的四大对象。返回的target是被重代理后的对象
5.3.Mybatis自定义插件的基础实现
MyBatis在启动时可以加载插件,并保存插件实例到相关对象(InterceptorChain,拦截器链) 中。
待准备工作做完后,MyBatis处于就绪状态。我们在执行SQL时,需要先通过DefaultSqlSessionFactory 创建 SqlSession。Executor 实例会在创建 SqlSession 的过程中被创建, Executor实例创建完毕后,
MyBatis会通过JDK动态代理为实例生成代理类。这样,插件逻辑即可在 Executor相关方法被调用前执行。
5.3.1.插件接口
Interceptor 接口,有以下方法:
- intercept ,插件的核心方法
- plugin,生成target的代理对象
- setProperties,传递插件所需的参数
5.3.2.开始实现自定义插件
-
代码实现
/** * 实现自定义插件,需要实现Interceptor接口。 * <p> * 使用@Intercepts注解,标注拦截器,并注定拦截的类和方法 */ @Intercepts( @Signature( //指定拦截sql语法构造器StatementHandler type = StatementHandler.class, //拦截的方法为prepare //只要执行到prepare预编译方法,都会先执行这个自定义插件的intercept方法 method = "prepare", //参数 args = {Connection.class, Integer.class}) ) public class Myplugin implements Interceptor { /** * 核心拦截方法,只要被拦截的目标方法被执行时,每次都会执行intercept方法 * * @param invocation * @return * @throws Throwable */ @Override public Object intercept(Invocation invocation) throws Throwable { //TODO 业务逻辑 //invocation.proceed是交还给原方法执行 return invocation.proceed(); } /** * 主要是把当前的拦截器生成代理类,添加到拦截器链中 * * @param target * @return */ @Override public Object plugin(Object target) { //this表示当前拦截器,target表示目标对象,wrap方法利用mybatis封装的方法为目标对象创建代理对象(没有拦截的对象会直接返回,不会创建代理对象) Object wrap = Plugin.wrap(target, this); return wrap; } /** * 获取配置的参数 * * @param properties */ @Override public void setProperties(Properties properties) { //properties对应的数据就是xml配置的property } } -
在sqlMapConfig.xml中配置:
<!--配置插件--> <plugins> <plugin interceptor="com.otoomo.plugin.Myplugin"> <!--配置插件的参数,在插件的setProperties的方法中可以获取到--> <property name="name" value="tom"/> </plugin> </plugins>配置文件的位置需要注意,不要放错,mybatis有严格的顺序校验,放错位置
5.3.3.插件的源码分析
5.3.4.使用插件编写通用的Mapper
- 基于Mybatis的插件机制
- 为了解决通用的单表CURD操作,不需要编写sql
-
在pom.xml中引入依赖
<dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper</artifactId> <version>3.1.2</version> </dependency> -
在sqlMapConfig.xml添加plugin配置
<plugins> <!--通用Mapper插件配置--> <plugin interceptor="tk.mybatis.mapper.mapperhelper.MapperInterceptor"> <!-- 通用Mapper接口,指定通用mapper接口是哪个 多个通用接口用逗号隔开 --> <property name="mappers" value="tk.mybatis.mapper.common.Mapper"/> </plugin> </plugins> -
编写实体类
@Table("user") public class User{ //指定主键 @Id //指定ID生成策略 @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private String username; } -
创建Mapper
/** * 继承Mapper即可实现通用Mapper */ public interface UserMapper extends Mapper<User>{ } -
代码演示
@org.junit.Test public void testCommonMapper() { //插入 Order addOrder = new Order(); addOrder.setUserId(1); addOrder.setOrderTime(new Date()); orderMapper.insert(addOrder); System.out.println(addOrder); //查询 Order query = new Order(); query.setId(1); Order order = orderMapper.selectOne(query); System.out.println(order); //自定义查询 Example example = new Example(Order.class); //创建一个查询条件e //还有很多方式,如 andLike,andBetween ... example.createCriteria().andEqualTo("userId",1); List<Order> orders = orderMapper.selectByExample(example); for (Order order1 : orders) { System.out.println(order1); } }