说明:基于 MyBatis 有很多第三方功能插件,这些插件可以完成数据操作方法的封装、数据库逆向工程的生成等。
tkMapper和MyBatis-plus都是基于 MyBatis 提供的第三方插件,功能类似,下面介绍 tkMapper 的使用。
tkMapper 就是一个 MyBatis 插件,基于 MyBatis 提供很多工具,提高开发效率,主要有以下两个功能。
tkMapper 的使用需要基于 MyBatis。
创建 Spring Boot 项目,选中 Lombok、Spring Web、MyBatis Framework、MySQL Driver 依赖
application.yml 配置文件中配置相关信息
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springdb?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8
username: root
password: luis
mybatis:
type-aliases-package: com.luis.beans
mapper-locations: classpath:mappers/*Mapper.xml
注意:配置后,手动创建 beans 和 mappers 文件夹
创建 dao 文件夹,在启动类上添加 dao 的包扫描器 @MapperScan(basePackages = {"com.luis.dao"})
添加依赖
<!-- tkMapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
如果自己在 maven 仓库中搜索,注意搜索关键词:mapper starter

PS:添加后,注意手动刷新 pom
更换启动类上 dao 包的包扫描器来源,不使用原先的 @MapperScan,要使用新添加的 tkMapper 的 @MapperScan
import tk.mybatis.spring.annotation.MapperScan;
@SpringBootApplication
@MapperScan(basePackages = {"com.luis.dao"}) //使用tkMapper的包扫描器注解
public class SpringbootTkMapperDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootTkMapperDemoApplication.class, args);
}
}
PS:注意注解的包来源 import tk.mybatis.spring.annotation.MapperScan
以上,tkMapper 环境已经搭建完成
tkMapper 提供针对单表通用的数据库操作方法。
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`user_pwd` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`user_realname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`user_img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "users") //数据库表名和实体类类名不一致需要指定映射关系!
public class User {
@Id //指定主键
private Integer userId;
private String userName;
private String userPwd;
private String userRealname;
private String userImg;
}
注意:创建的 Dao 接口需要继承 tkMapper 中提供的 Mapper 和 MySqlMapper 两个接口,这两个接口提供了对单表的通用操作。
public interface UserDao extends Mapper<User>, MySqlMapper<User> {
}
可选优化策略【建议使用】:
如果不想每次创建 dao 接口时都继承 tkMapper 中的两个接口,可以自己写一个通用的接口模板,只需要让这个通用的接口模板继承 tkMapper 中的两个接口,然后自己创建的 dao 接口只需要继承这个通用的接口模板即可!
但是,需要注意的是,这个通用的接口模板千万不能写在 dao 目录下!因为 dao 目录下的接口会被扫描到,有固定的功能用处;而我们自定义的通用接口模板只是为了继承,没有其他特殊功能!
使用示例:
1、可在 dao 目录同级创建 general 目录,在 general 目录下创建 GeneralDao 接口,并继承 tkMapper 中的两个接口。
package com.luis.general; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.common.MySqlMapper; /** * @Author: Luis * @date: 2022/11/9 14:39 * @description: 自定义的通用接口模板 */ public interface GeneralDao<T> extends Mapper<T>, MySqlMapper<T> { }2、创建 dao 接口,继承 GeneralDao 即可!
public interface UserDao extends GeneralDao<User> { }
添加 Junit 和 springboot test 两个测试依赖:
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- springboot test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
写测试类进行测试:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
public class UserDaoTest {
@Autowired
private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
@Test
public void test() {
User user = new User();
user.setUserName("mike");
user.setUserPwd("123");
user.setUserRealname("zhangsan");
user.setUserImg("user/default.jpg");
int i = userDao.insert(user);
System.out.println("========> i = " + i);
}
}
insert:普通添加insertUseGeneratedKeys:可返回自增 id 的添加updateByPrimaryKey:根据主键修改deleteByPrimaryKey:根据主键删除@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
public class UserDaoTest {
@Autowired
private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
@Test
public void testInsert() {
User user = new User();
user.setUserName("juno4");
user.setUserPwd("321");
user.setUserRealname("lin");
user.setUserImg("user/default.jpg");
/**
* insert: 添加(自增的id不会返回)
*/
int i = userDao.insert(user);
System.out.println("========> i = " + i);
System.out.println(user.getUserId()); //null
}
@Test
public void testInsertUseGeneratedKeys() {
User user = new User();
user.setUserName("juno3");
user.setUserPwd("321");
user.setUserRealname("lin");
user.setUserImg("user/default.jpg");
/**
* insertUseGeneratedKeys: 添加(自增的id可以返回)
* 注意:
* 1. 数据库中主键字段需要设置为自增
* 2. 实体类中主键属性需要使用@Id注解指定;并且需要使用包装类型Integer,不要使用int
*/
int i = userDao.insertUseGeneratedKeys(user);
System.out.println("========> i = " + i);
System.out.println(user.getUserId()); //10
}
@Test
public void testUpdateByPrimaryKey() {
User user = new User();
user.setUserId(10); //必须指定要修改的id
user.setUserName("juno new");
user.setUserPwd("000");
user.setUserRealname("lin new");
user.setUserImg("new.jpg");
/**
* updateByPrimaryKey:根据主键修改
*/
int i = userDao.updateByPrimaryKey(user);
System.out.println("========> i = " + i);
System.out.println(user);
}
@Test
public void testDeleteByPrimaryKey() {
/**
* deleteByPrimaryKey:根据主键删除
*/
int i = userDao.deleteByPrimaryKey(9);
System.out.println("========> i = " + i);
}
}
PS:其实还有根据自定义条件修改或删除的方法(使用方法参考带条件的查询示例)
selectAll:查所有selectByPrimaryKey:根据主键查所有selectByExample:根据条件查所有selectByRowBounds:分页查询selectByExampleAndRowBounds:带条件的分页查询selectCount:查总记录数selectCountByExample:根据条件查总记录数@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
public class UserDaoTest {
@Autowired
private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
@Test
public void testSelectAll() {
/**
* selectAll:查询所有
*/
List<User> users = userDao.selectAll();
for (User user : users) {
System.out.println(user);
}
}
@Test
public void testSelectByPrimaryKey() {
/**
* selectByPrimaryKey:根据主键查询
*/
User user = userDao.selectByPrimaryKey(10);
System.out.println(user);
}
@Test
public void testSelectByExample() {
//封装查询条件
Example example = new Example(User.class);
Example.Criteria criteria = example.createCriteria();
//条件信息(根据Criteria对象的各种方法进行设置)
criteria.andEqualTo("userRealname", "lin");
// criteria.orEqualTo("userPwd", "123");
// criteria.andLike("userName", "%i%");
/**
* selectByPrimaryKey:根据条件查询(PS:根据条件修改或删除与此类似)
* 注意:需要设置查询条件信息,并传入条件对象
*/
List<User> users = userDao.selectByExample(example);
for (User user : users) {
System.out.println("========> " + user);
}
}
@Test
public void testSelectByRowBounds() {
//分页查询信息
int pageNum = 2; //第几页
int pageSize = 3; //每页显示多少行
int start = (pageNum - 1) * pageSize; //起始显示的下标
RowBounds rowBounds = new RowBounds(start, pageSize);
/**
* selectByRowBounds:查所有的分页查询
*/
List<User> users = userDao.selectByRowBounds(new User(), rowBounds);
for (User user : users) {
System.out.println("========> " + user);
}
/**
* selectCount:查询总记录数
*/
int count = userDao.selectCount(new User());
System.out.println("========> count = " + count);
}
@Test
public void testSelectByExampleAndRowBounds() {
//封装查询条件
Example example = new Example(User.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("userRealname", "lin");
//分页查询信息
int pageNum = 2; //第几页
int pageSize = 2; //每页显示多少行
int start = (pageNum - 1) * pageSize; //起始显示的下标
RowBounds rowBounds = new RowBounds(start, pageSize);
/**
* selectByExampleAndRowBounds:带条件的分页查询
*/
List<User> users = userDao.selectByExampleAndRowBounds(example, rowBounds);
for (User user : users) {
System.out.println("========> " + user);
}
/**
* selectCountByExample:根据条件查询总记录数
*/
int count = userDao.selectCountByExample(example);
System.out.println("========> count = " + count);
}
}
说明:所有的关联/多表查询都可以由多个单表查询组成
关联/多表查询实现方式:
方式一:多次使用单表查询,然后封装数据
方式二:自定义查询方法和 SQL
情景:基于以上的用户表,新添加一个订单表 orders,订单表中有订单信息,但是也有用户 id;
要求:在查询用户表的同时还要查询出用户的订单信息,这就涉及到了两张表的查询。
具体业务要求:根据用户名查询用户的所有信息,包括订单信息。
新建订单表 orders:
DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
`order_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`receiver_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`receiver_mobile` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`receiver_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`order_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
INSERT INTO `orders` VALUES (1, 1, 'luis', '13344445555', '湖北武汉');
新建实体类 Order:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "orders")
public class Order {
@Id
private Integer orderId;
private Integer userId;
private String receiverName;
private String receiverMobile;
private String receiverAddress;
}
新建 dao 接口:
注意,此处 dao 接口继承的是自定义的通用接口模板,相关说明参见之前创建示例 UserDao 的步骤。
也可以直接继承 tkMapper 的两个接口。(注意灵活运用!)
public interface OrderDao extends GeneralDao<Order> {
}
说明:进行关联/多表查询前,需要修改下之前的 User 实体类,在实体类中需要添加一个订单的字段,以便查询出用户所关联的订单信息。
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "users") //数据库表名和实体类类名不一致需要指定映射关系!
public class User {
@Id //指定主键
private Integer userId;
private String userName;
private String userPwd;
private String userRealname;
private String userImg;
//订单
private List<Order> orderList;
}
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
public class UserDaoTest {
@Autowired
private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
@Autowired
private OrderDao orderDao;
@Test
public void test() {
//根据用户名查询用户信息
Example example = new Example(User.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("userName", "luis");
//条件查询
List<User> users = userDao.selectByExample(example);
User user = users.get(0);
//根据用户id查询订单信息
Example example1 = new Example(Order.class);
Example.Criteria criteria1 = example.createCriteria();
criteria.andEqualTo("userId", user.getUserId());
//条件查询
List<Order> orders = orderDao.selectByExample(example1);
//将查询到的订单信息设置到user中
user.setOrderList(orders);
System.out.println("========> " + user);
}
}
UserDao 接口中新建查询方法
public interface UserDao extends GeneralDao<User> {
public User selectByUserName(String userName);
}
mappers 目录下创建对应的 UserMapper.xml 文件,自定义查询 SQL
<?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="com.luis.dao.UserDao">
<resultMap id="userMap" type="com.luis.beans.User">
<id column="user_id" property="userId"/>
<result column="user_name" property="userName"/>
<result column="user_pwd" property="userPwd"/>
<result column="user_realname" property="userRealname"/>
<result column="user_img" property="userImg"/>
<collection property="orderList" ofType="com.luis.beans.Order">
<id column="order_id" property="orderId"/>
<result column="user_id" property="userId"/>
<result column="receiver_name" property="receiverName"/>
<result column="receiver_mobile" property="receiverMobile"/>
<result column="receiver_address" property="receiverAddress"/>
</collection>
</resultMap>
<select id="selectByUserName" resultMap="userMap">
select u.user_id,u.user_name,u.user_pwd,u.user_realname,u.user_img,
o.order_id,o.user_id,o.receiver_name,o.receiver_mobile,o.receiver_address
from users u inner join orders o
on u.user_id = o.user_id;
</select>
</mapper>
测试
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
public class UserDaoTest {
@Autowired
private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
@Autowired
private OrderDao orderDao;
@Test
public void test02() {
//使用自定义的查询方法
User user = userDao.selectByUserName("luis");
System.out.println("========> " + user);
}
}
| anno | desc |
|---|---|
| @Id | 标记该字段为数据库主键 |
| @KeySql(useGeneratedKeys = true) | 主键生成策略,使用 JDBC 的方式获取数据库自增的主键值 |
| @Table(name = "country") | 表名 |
| @Column(name = "user_name") | 数据库映射字段 |
| @Transient | 表明非数据库字段 |
T selectOne(T record)
根据实体中的属性进行查询,只能有一个返回值,有多个结果则抛出异常,查询条件使用等号
Listrecord)
根据实体中的属性值进行查询,查询条件使用等号
List
查询全部结果
int selectCount(T record)
根据实体中的属性查询总数,查询条件使用等号
T selectByPrimaryKey(Object key)
根据主键字段进行查询,方法参数必须包含完整的主键属性,查询条件使用等号
boolean existsWithPrimaryKey(Object key)
根据主键字段查询总数,方法参数必须包含完整的主键属性,查询条件使用等号
List
根据example条件进行查询一条或多条数据
selectOneByExample(Object example)
根据example条件查询一条数据
selectCountByExample(Object example)
根据example条件查询记录数
ListRowBounds rowBounds);
根据example条件和RowBounds进行分页查询
ListRowBounds rowBounds);
根据实体属性和RowBounds进行分页查询
int insert(T record)
保存一个实体,实体中缺省的属性也会保存,使用null保存而不是数据库默认值
int insertSelective(T record)
保存一个实体,null的属性不会保存,会使用数据库默认值,无默认值则使用null
int updateByPrimaryKey(T record)
根据主键更新实体全部字段,实体中缺省的字段也会被更新,被更新为null
int updateByPrimaryKeySelective(T record)
根据主键更新属性不为null的值,实体中缺省的字段不会被更新
int updateByExample(@Param("record") T record, @Param("example") Object example)
根据example条件更新实体record包含的全部属性,实体中缺省的值也会被更新,更新为null
int updateByExampleSelective(@Param("record") T record, @Param("example") Object example)
根据example条件更新实体record包含的不是null的属性值,实体中缺省的字段不会被更新
int delete(T record)
根据实体属性作为条件进行删除,查询条件使用等号
int deleteByPrimaryKey(object key)
根据主键字段进行删除,方法参数必须包含完整的主键属性
int deleteByExample(Object example)
根据example条件删除数据
Example example = new Example(xxx.class);
| method | desc |
|---|---|
| example.setOrderByClause("字段名 DESCASC") | 添加升序排列条件,DESC 为降序 |
| example.setDistinct(false) | 是否去重 |
| example.orderBy("pid") | 排序,order by pid,默认为 ASC |
| example.orderBy("pid").desc() | 逆序排序 |
| example.selectProperties("id", "pid", …) | 选择查询的列,select id , pid … |
| example.excludeProperties("name", "icon") | 排除查询的列,结果不显示 |
| example.and().andEqualTo("id", 4) | 等值查询,and id = 4 |
| example.and().andLike("pid", "%5%") | 模糊查询:and pid like %5% |
| example.and().andBetween("id", 5, 8) | 区间查询:and (id betewwn 5 and 8) |
| ... | ... |
Example.Criteria criteria = example.createCriteria();
| method | desc |
|---|---|
| criteria.andIsNull() | 字段为 null |
| criteria.andNotNull() | 字段不为 null |
| criteria.andEqualTo() | 字段等于 |
| criteria.andNotEqualTo() | 字段不等于 |
| criteria.andGreaterThan() | 字段大于 |
| criteria.andGreaterThanOrEqualTo() | 字段大于等于 |
| criteria.andLessThan() | 字段小于 |
| criteria.andLessThanOrEqualTo() | 字段小于等于 |
| criteria.andIn() | 字段在 List<?> 中 |
| criteria.andNotIn() | 字段不在 List<?> 中 |
| criteria.andLike("%" + value + "%") | 字段为 value 的模糊查询条件 |
| criteria.andNotLike("%" + value + "%") | 字段不为 value 的模糊查询条件 |
| criteria.andBetween(value1, value2) | 字段在 value1 和 value2 之间 |
| criteria.andNotBetween(value1, value2) | 字段不在 value1 和 value2 之间 |
| ... | ... |
所谓逆向工程,就是通过数据库表,来自动生成实体类、dao 接口和 mapper 文件。
需要注意的是,本逆向工程是最好配合 tkMapper 环境使用,因为,有一些配置和 tkMapper 相关,如生成的 dao 接口会继承自定义的通用接口模板,而该通用的接口模板就是继承了 tkMapper 中的两个接口,从而才能使用 tkMapper 提供的通用数据操作方法;还有,生成的实体类上的注解需要依赖 tkMapper 环境。
重要说明:本逆向工程使用的 mysql 版本是低版本 5.1.36!经测试,如果使用高版本如 8.xxx,很大概率会生成有问题!所以建议项目中统一使用低版本的 MySQL。
在 pom.xml 中 build 的 plugins 下添加下列生成器插件
<!-- mybatis-generator-maven-plugin -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.6</version>
<!-- 生成器配置文件位置;如果还没有添加,可以先注释,添加后再放开 -->
<configuration>
<configurationFile>
${basedir}/src/main/resources/generator/GeneratorConfig.xml
</configurationFile>
</configuration>
<!-- 插件所需的两个依赖 -->
<dependencies>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.36</version>
</dependency>
<!-- mapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.1.5</version>
</dependency>
</dependencies>
</plugin>
注意:推荐直接复制,但如果想自己在 maven 仓库中搜索,注意关键词:mybatis-generator-maven-plugin,并且,千万注意,你搜索到的肯定是依赖,而并非插件!此时,你只需要复制依赖的 gav 坐标,自己在 pom 中创建空 plugin 标签,将 gav 坐标复制进去即可!(如果相关依赖刷新添加失败,可以复制到 dependences 下,重新刷新添加试试,添加成功后复制回来即可)
注意查看项目中是否自定义有通用接口模板 GeneralDao,使其继承 tkMapper 的两个接口;如果没有,则在 dao 同级目录,创建 general 目录,在 general 目录下创建自定义通用接口模板 GeneralDao,继承 tkMapper 的两个接口;
public interface GeneralDao<T> extends Mapper<T>, MySqlMapper<T> {
}
在 resources/generator 下添加 GeneratorConfig.xml 生成器配置(创建并复制后改主要配置即可)
主要需要配置:配置数据库连接、配置实体类存放路径、配置 XML 存放路径、配置 DAO 存放路径、配置 GeneralDao
注意:默认配置是生成指定数据库中所有表,也可以自定义的指定只生成哪些表
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 引入数据库连接配置 -->
<!-- <properties resource="jdbc.properties"/>-->
<context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!-- 配置 GeneralDao -->
<plugin type="tk.mybatis.mapper.generator.MapperPlugin">
<property name="mappers" value="com.luis.general.GeneralDao"/>
</plugin>
<!-- 配置数据库连接(注意数据库版本问题,需要使用低版本的,高版本可能出现问题!) -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/springdb?serverTimezone=UTC"
userId="root" password="luis">
</jdbcConnection>
<!-- 配置实体类存放路径 -->
<javaModelGenerator targetPackage="com.luis.beans" targetProject="src/main/java"/>
<!-- 配置 XML 存放路径 -->
<sqlMapGenerator targetPackage="/" targetProject="src/main/resources/mappers"/>
<!-- 配置 Dao 存放路径 -->
<javaClientGenerator targetPackage="com.luis.dao" targetProject="src/main/java" type="XMLMAPPER"/>
<!-- 配置需要指定生成的数据库和表,% 代表所有表 -->
<table tableName="%">
<!-- mysql 配置 -->
<!-- <generatedKey column="id" sqlStatement="Mysql" identity="true"/>-->
</table>
<!-- <table tableName="tb_roles">-->
<!-- <!– mysql 配置 –>-->
<!-- <generatedKey column="roleid" sqlStatement="Mysql" identity="true"/>-->
<!-- </table>-->
<!-- <table tableName="tb_permissions">-->
<!-- <!– mysql 配置 –>-->
<!-- <generatedKey column="perid" sqlStatement="Mysql" identity="true"/>-->
<!-- </table>-->
</context>
</generatorConfiguration>
打开 IDEA 右侧 Maven 窗口,找到项目--》Plugins--》mybatis-generator--》mybatis-generator:generate,双击执行逆向生成即可!
示例图:

查看 beans、dao、mappers 目录下的生成情况,看生成的相关接口是否符合开发要求,根据情况可做相关修改,然后进行相关测试。
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po