我就用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的性能优势!

相关推荐
白帽攻防录7 小时前
SRC 挖洞:Roundcube 预认证 SQL 注入深度复盘,CVE-2026-48842 preg_replace 转义绕过怎么打穿邮件系统
网络·数据库·sql·网络安全·sql注入
꯭自꯭闭꯭7 小时前
达梦SQL优化相关
linux·运维·数据库·sql
shuoshuohaohao7 小时前
MyBatis 小知识点
java·spring·mybatis
对空六课8 小时前
支持注意力分析的热力图工具有哪些?
前端·数据库·数据分析
南京码讯光电技术有限公司8 小时前
How to Design an Antenna System for an Industrial WiFi Module
数据库·人工智能
lusklusklusk9 小时前
Oracle数据库基础之2_体系结构
数据库·oracle
可乐ea9 小时前
从第一性原理构建 AI Agent:提示词、工具、技能与记忆全解剖
数据库·人工智能·工具调用·ai智能体·提示词工程·agent开发·智能体记忆
东方护航数据恢复(深圳)10 小时前
医疗案例:HIS/PACS 数据库页损坏修复,医院不停诊完成恢复【东方护航数据恢复深圳店】
数据库·数据恢复·医疗·二次开盘
lusklusklusk11 小时前
Oracle数据库基础之11_Duplicate和Dataguard和RAC
数据库·oracle
PHP实战开发录12 小时前
MySQL字段加索引为什么没变快
数据库·mysql·php·开发