对JDBC、DataSource、hibernate、MyBatis的一点看法

本文对比分析了JDBC、Hibernate和MyBatis三种数据库操作方式的特点与应用场景,详细介绍了各自的优缺点,包括JDBC的基础操作、Hibernate的ORM特性及MyBatis的手动SQL编写灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、JDBC

  JDBC是一种基准,是java连接各大厂商的关系型数据库的接口规范。

/**
*
* @description: JDBC连接MySQL数据库进行CRUD操作
* 
* 步骤: 
* 1、加载驱动和注册数据库信息。 
* 2、打开Connection,获取PreparedStatement对象。
* 3、通过PreparedStatement执行SQL,返回结果到ResultSet对象。
* 4、使用ResultSet读取数据,然后通过代码转换为具体的POJO对象。 
* 5、关闭数据库相关资源,先开的后关,后开的先关。
*
* 
*/
public class JdbcTest {
  private Logger logger = LoggerFactory.getLogger(getClass());
  private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
  private static final String URL = "jdbc://mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8";
  private static final String USERNAME = "root";
  private static final String PASSWORD = "root";

  private Connection getConnection() {
    Connection conn = null;
    try {
      // 加载驱动和注册数据库信息
      Class.forName(JDBC_DRIVER);
      DriverManager.getConnection(URL, USERNAME, PASSWORD);
    } catch (ClassNotFoundException | SQLException e) {
      logger.info("Class={JdbcTest.class.getName()} not found", JdbcTest.class.getName(), e);
    }
    return conn;
  }

  /**
  * 
  * @description: 保存用户信息
  * @param user
  * @return
  */
  public int save(User user) {
    Connection conn = getConnection();
    int row = 0;
    // 5个问号(占位符)代表5个字段预先要保留的值
    String sql = "insert into tb_user (username,password,name,sex,email,tel) values(?,?,?,?,?,?)";
    PreparedStatement ps = null;
    try {
      /**
      * 使用PreparedStatement的优点:
      * 1、具有预编译功能,相同的SQL语句只需要编译一次,提高执行效率。
      * 2、可以防止SQL语句注入,提高安全性
      */
      // 使用PreparedStatement对象里来构建并执行SQL语句
      ps = conn.prepareStatement(sql);
      // 通过PreparedStatement对象里的set方法设置要插入的值
      ps.setString(1, user.getUsername());
      ps.setString(2, user.getPassword());
      ps.setString(3, user.getName());
      ps.setInt(4, user.getSex());
      ps.setString(5, user.getEmail());
      ps.setString(6, user.getTel());
      // 返回影响行数
      row = ps.executeUpdate();
    } catch (SQLException e) {
      logger.info("Bad SQL Grammer", e);
    } finally {
      close(null, ps, conn);
    }
    return row;
  }

  /**
  * 
  * @description: 释放资源,注意:先开的后关,后开的先关
  * @param rs
  * @param ps
  * @param conn
  */
  public void close(ResultSet rs, PreparedStatement ps, Connection conn) {
    try {
      if (rs != null && rs.isClosed()) {
        rs.close();
      }
    } catch (SQLException e1) {
      e1.printStackTrace();
    }
    try {
      if (ps != null && ps.isClosed()) {
        ps.close();
    }
    } catch (SQLException e) {
      e.printStackTrace();
    }
    try {
      if (conn != null && conn.isClosed()) {
        conn.close();
      }
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }
}

  JDBC需要自己维护connection,ResultSet,SQL,底层事务;频繁的连接和断开数据库,性能开销还是很大的。

2、hibernate

public class ActivityCouponDao extends GenericDaoHibernate<CouponPool, Long> {

    public ActivityCouponDao() {
        super(CouponPool.class);
    }

    /**
     * @Author mayutao
     * @CreatedDate 2019/8/29
     * @Description 根据id进行模糊查询
     * @Param id
     * @Return List<Map>
     */
   public List<Map> queryCouponList(Long id) {
        StringBuilder sql = new StringBuilder("select id, coupon_name as name, subhead ");
        sql.append(" from coupon_pool  ");
        sql.append(" where id like :id ");
       sql.append(" AND status = 1 ");
       sql.append(" AND type_id = 1 ");
        sql.append(" order by update_time desc ");
        Query query = getReadSession().createSQLQuery(sql.toString()).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        query.setString("id", id.toString() + "%");

        return (List<Map>) query.list();
    }

    /**
     * @Author mayutao
     * @CreatedDate 2020/1/15
     * @Description 模糊查询,分页获取红包数据
     * @Param pageable
     * @Return Page<CouponPool>
     */
    public Page<CouponPool> queryCouponPage(Long couponId, Pageable pageable){
        Criteria criteria = getReadSession().createCriteria(CouponPool.class);
        if(couponId != null){
            criteria.add(Restrictions.eq("id", couponId));
        }
        criteria.add(Restrictions.eq("isDeleted", false));
        criteria.add(Restrictions.eq("status", 1));
        criteria.add(Restrictions.eq("typeId", CouponTypeEnum.POLICY_HB.getTypeId()));

        Long rowCount = (Long) criteria.setProjection(
                Projections.rowCount()).uniqueResult();
        criteria.setProjection(null);
        criteria.addOrder(Order.desc("updateTime"));
        criteria.setFirstResult(pageable.getOffset());
        criteria.setMaxResults(pageable.getPageSize());
        List data = criteria.list();
        return new PageImpl(data, pageable, rowCount == null ? 0 : rowCount);
    }
}

  hibernate是ORM框架,ORM框架是使得数据库的访问转变成对对象的访问,将关注点转向业务,简化SQL编写。
  hibernate的优势,对JDBC的代码进行了封装,使我们的编程更简便了,不用写SQL语句,提高了开发效率。消除了代码的映射规则,也无需在管理数据库连接,全部被分离到了XML或注解里面去配置。一个会话中,不需要操作多个对象,只要操作Session即可,关闭资源也只要关闭一个Session即可,不用频繁开启关闭数据库连接。当然在Spring的集成使用下这些都会交由Spring来管理,使用更加方便。
  hibernate的优势, 当我们更新时将发送所有的字段,而当我们查询时它也会将我们不想要查询的字段也查询出来(部分查询方式),这即是全表映射所带来的麻烦。hibernate并不能很好的支持存储过程,一大遗憾。对多表关联和复杂SQL查询支持稍差,还是要自己写SQL语句,返回的结果,需要自己组装为POJO。虽然hibernate使用的是HQL语言查询,但是性能不高。而当我们的数据量很大或是大型系统时,必定需要优化SQL语句。由于hibernate的高门槛,要完全掌握并不简单,所以对于一个开始并不熟悉hibernate开发的人,学习时间稍长,开发速度稍慢。

3、MyBatis

  mybatis是一个半自动化的框架,何谓半自动,因为它需要手工编写POJO、SQL和映射关系。

public interface UserMapper {
    /**
     * 新增用戶
     * @param user
     * @return
     * @throws Exception
     */
    public int insertUser(UserBean user) throws Exception;
    /**
     * 修改用戶
     * @param user
     * @param id
     * @return
     * @throws Exception
     */
    public int updateUser (UserBean user,int id) throws Exception;
     /**
      * 刪除用戶
      * @param id
      * @return
      * @throws Exception
      */
    public int deleteUser(int id) throws Exception;
    /**
     * 根据id查询用户信息
     * @param id
     * @return
     * @throws Exception
     */
    public UserBean selectUserById(int id) throws Exception;
     /**
      * 查询所有的用户信息
      * @return
      * @throws Exception
      */
    public List<UserBean> selectAllUser() throws Exception;
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cy.mybatis.mapper.UserMapper">
<!-- 自定义返回结果集 -->
   <resultMap id="userMap" type="UserBean">
        <id property="id" column="id" javaType="java.lang.Integer"></id>
        <result property="username" column="username" javaType="java.lang.String"></result>
        <result property="password" column="password" javaType="java.lang.String"></result>
        <result property="account" column="account" javaType="java.lang.Double"></result>
    </resultMap>
<!-- 在各种标签中的id属性必须和接口中的方法名相同 , id属性值必须是唯一的,不能够重复使用。parameterType属性指明查询时使用的参数类型,resultType属性指明查询返回的结果集类型-->    
<!-- useGeneratedKeys:( 仅 对 insert 有 用 ) 这 会 告 诉 MyBatis 使 用 JDBC 的getGeneratedKeys 
            方法来取出由数据(比如:像 MySQL 和 SQLServer 这样的数据库管理系统的自动递增字段)内部生成的主键。默认值: false。 -->    
<!--keyProperty: (仅对 insert有用)标记一个属性, MyBatis 会通过 getGeneratedKeys或者通过 insert 语句的 selectKey 子元素设置它的值。默认:不设置。 -->
<!--#{}中的内容,为占位符,当参数为某个JavaBean时,表示放置该Bean对象的属性值  -->
    <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
        insert into t_user (username,password,account) values (#{username},#{password},#{account})
    </insert>
    
    <update id="updateUser" >
      update t_user set username=#{username},password=#{password},account=#{account} where id=#{id}
    </update>
    
    <delete id="deleteUser" parameterType="int">
     delete from t_user where id=#{id}  
    </delete>
    
    <select id="selectUserById" parameterType="int" resultMap="userMap">
     select * from t_user where id=#{id}
    </select>
    
    <select id="selectAllUser" resultMap="userMap">
     select * from t_user
    </select>
</mapper>

  MyBatis可以自定义一些复杂的SQL和自定对象,对于大厂对SQL管理严格的项目,Mybatis比较合适。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值