明白了!你想用 MyBatis 作为主要数据库交互工具 ,但同时享受 ORM 的便利性。最好的方案是:
方案:MyBatis-Plus + 代码生成器(最主流)
1. 项目结构
src/main/java/
├── entity/ # 实体类(ORM核心)
├── mapper/ # Mapper接口
├── service/ # 业务层
└── controller/ # 控制层
2. 依赖配置
xml
<dependencies>
<!-- MyBatis-Plus Starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.4.1</version>
</dependency>
<!-- 代码生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.4.1</version>
</dependency>
<!-- 模板引擎 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.32</version>
</dependency>
</dependencies>
3. 基础实体类(ORM核心)
java
@Data
public class BasePO {
@TableId(type = IdType.AUTO)
private Long id;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(fill = FieldFill.INSERT)
private Long createUser;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;
}
4. 自动生成影视实体类
java
// Movie.java - 电影实体
@Data
@TableName("movie")
@EqualsAndHashCode(callSuper = true)
public class Movie extends BasePO {
private String title;
private String originalTitle;
private Integer releaseYear;
private Integer duration;
private BigDecimal rating;
private String description;
private String posterUrl;
private String country;
private String language;
private Long directorId;
// 关联字段(不映射到数据库)
@TableField(exist = false)
private String directorName;
@TableField(exist = false)
private List<Actor> actors;
}
// Actor.java - 演员实体
@Data
@TableName("actor")
@EqualsAndHashCode(callSuper = true)
public class Actor extends BasePO {
private String name;
private String englishName;
private Integer gender;
private LocalDate birthday;
private String country;
private String biography;
private String avatarUrl;
}
5. 自动生成 Mapper
java
// 自动生成的基础Mapper
@Mapper
public interface MovieMapper extends BaseMapper<Movie> {
// 继承后自动拥有:
// insert, deleteById, updateById, selectById, selectList, selectPage 等方法
}
@Mapper
public interface ActorMapper extends BaseMapper<Actor> {
// 基础CRUD方法自动实现
}
6. 自定义复杂查询(手写SQL)
java
@Mapper
public interface MovieMapper extends BaseMapper<Movie> {
// 复杂查询:电影详情(包含导演和演员)
@Select("SELECT m.*, d.name as director_name " +
"FROM movie m " +
"LEFT JOIN director d ON m.director_id = d.id " +
"WHERE m.id = #{movieId}")
Movie selectMovieDetail(@Param("movieId") Long movieId);
// 复杂查询:分页搜索
@Select("<script>" +
"SELECT m.*, d.name as director_name " +
"FROM movie m " +
"LEFT JOIN director d ON m.director_id = d.id " +
"WHERE 1=1 " +
"<if test='title != null'> AND m.title LIKE CONCAT('%', #{title}, '%') </if>" +
"<if test='minRating != null'> AND m.rating >= #{minRating} </if>" +
"<if test='startYear != null'> AND m.release_year >= #{startYear} </if>" +
"<if test='endYear != null'> AND m.release_year <= #{endYear} </if>" +
"ORDER BY m.rating DESC " +
"LIMIT #{offset}, #{limit}" +
"</script>")
List<Movie> searchMovies(@Param("title") String title,
@Param("minRating") BigDecimal minRating,
@Param("startYear") Integer startYear,
@Param("endYear") Integer endYear,
@Param("offset") Long offset,
@Param("limit") Integer limit);
}
7. 服务层使用(享受ORM便利)
java
@Service
public class MovieService {
@Autowired
private MovieMapper movieMapper;
@Autowired
private ActorMapper actorMapper;
/**
* 简单CRUD - 像ORM一样使用
*/
public void addMovie(Movie movie) {
movieMapper.insert(movie); // 自动填充createTime等字段
}
public Movie getMovie(Long id) {
return movieMapper.selectById(id); // 自动映射到实体
}
public void updateMovie(Movie movie) {
movieMapper.updateById(movie); // 自动填充updateTime
}
public void deleteMovie(Long id) {
movieMapper.deleteById(id); // 简单删除
}
public List<Movie> listMovies() {
return movieMapper.selectList(null); // 查询所有
}
/**
* 复杂业务 - 使用自定义SQL
*/
public List<Movie> searchHighRatedMovies(String keyword) {
return movieMapper.searchMovies(keyword,
new BigDecimal("8.0"), 2020, 2024, 0L, 20);
}
/**
* 关联查询
*/
public Movie getMovieWithActors(Long movieId) {
Movie movie = movieMapper.selectMovieDetail(movieId);
if (movie != null) {
// 查询关联的演员
List<Actor> actors = actorMapper.selectActorsByMovieId(movieId);
movie.setActors(actors);
}
return movie;
}
}
8. 自动填充配置
java
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "createUser", Long.class, getCurrentUserId());
this.strictInsertFill(metaObject, "updateUser", Long.class, getCurrentUserId());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
this.strictUpdateFill(metaObject, "updateUser", Long.class, getCurrentUserId());
}
private Long getCurrentUserId() {
// 从安全上下文获取当前用户ID
return 1L; // 实际项目中从登录信息获取
}
}
优势总结
✅ 真正的ORM体验 :实体类操作,自动映射
✅ 性能可控 :复杂查询手写SQL优化
✅ 开发效率 :代码生成器快速生成基础代码
✅ 灵活性 :既享受ORM便利,又保持SQL灵活性
✅ 主流方案:大厂广泛使用,社区活跃
这就是 MyBatis-Plus 的"半ORM"方案 - 既享受了ORM的开发效率,又保持了MyBatis的性能优势!