對JDBC、DataSource、hibernate、MyBatis的一點看法

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比較合適。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章