我就用mybatis作为与数据库交互,但我想用orm,最好的实现方案是啥

明白了!你想用 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的性能优势!

相关推荐
YOU OU7 小时前
Redis基础常识与命令
数据库·redis·缓存
Database_Cool_10 小时前
OLTP 和 OLAP 区别详解:分析型数据库和事务型数据库怎么选(附阿里云 AnalyticDB MySQL 选型指南)
数据库·mysql·阿里云
爱写代码的阿森10 小时前
鸿蒙三方库 | harmony-utils之KvUtil键值型数据库操作详解
数据库·华为·harmonyos·鸿蒙·huawei
Database_Cool_10 小时前
单机 MySQL 迁移到分布式数据库方便吗?阿里云 PolarDB-X 100% MySQL 协议兼容零改造平滑迁移
数据库·分布式·mysql
姜太小白11 小时前
【MySQL】 索引优化实战:解决 WHERE 等值 + IS NULL 查询,TEXT 字段报错 1167 的完整指南
数据库·mysql
窝子面12 小时前
手搓最简前后端协作-node
javascript·数据库
吳所畏惧12 小时前
宝塔面板Redis密码修改指南:SSH命令修改 vs 面板UI界面修改,哪个更靠谱?
运维·服务器·数据库·redis·缓存·ssh
DFT计算杂谈12 小时前
无 Root 权限在 Tesla K80 零门槛部署 DeepSeek 大模型
linux·服务器·网络·数据库·机器学习
HPFBoy12 小时前
log4net 数据库存日志正确配置
数据库