前言
.NET C#到Java沒那么難,都是面向對象的語言,而且語法還是相似的,先對比一下開發環境,再到Servlet,再到MVC,都是一樣一樣的,只是JAVA的配制項比較多而已,只要配好一個,后面都是copy,簡直so easy,而且用myeclipse可以省一些配制
Java與.NET的區別不在它們的本身,最大的區別在於他們背后的力量,相信大家都能感覺得到,我就不多說。
系列目錄
五、.NET C#到Java沒那么難,Nosql篇
六、.NET C#到Java沒那么難,微服務篇
七、.NET C#到Java沒那么難,大數據篇
.NET C#到Java沒那么難,DB篇
目錄
1.ADO.NET 和 JDBC
2.DBHelper 和 DBUtils
3.EF 和 Hibernate
4.Dapper 和 Mybatis
1.ADO.NET 和 JDBC
(1).ADO.NET和JDBC數據庫對象
ADO.NET |
JDBC |
Connection |
Connection |
Command、DataAdapter |
Statement、PreparedStatement |
DataReader 在線數據集 |
ResultSet |
DataTable、DataSet 離線數據集 |
RowSet |
Transaction |
Transaction |
(2)ADO.NET連接字符串 和 JDBC數據庫驅動和Url
2.JDBC數據庫驅動和Url
數據庫 |
驅動類名 |
URL格式 |
Oracle |
oracle.jdbc.driver.OracleDriver |
jdbc:oracle:thin:@hostip:1521:dbname |
Sybase |
com.sybase.jdbc2.jdbc.SybDriver |
jdbc:sybase:Tds:hostip:4100/dbname |
Mysql |
com.mysql.jdbc.Driver |
jdbc:mysql://hostip:3306/dbname?useUnicode=true&characterEncoding=GBK |
SQLServer 2000 |
com.microsoft.jdbc.sqlserver.SQLServerDriver |
jdbc:microsoft:sqlserver://hostip:1433;DatabaseName=dbname |
SQLServer 2005 |
com.microsoft.sqlserver.jdbc.SQLServerDriver |
jdbc:sqlserver://hostip:1433;DatabaseName=dbname |
SQLServer 7.0 |
net.sourceforge.jtds.jdbc.Driver |
jdbc:jtds:sqlserver://hostip:1433/dbname |
DB2 |
com.ibm.db2.jcc.DB2Driver |
jdbc:db2://hostip:50000/dbname |
Informix |
com.informix.jdbc.IfxDriver |
jdbc:informix-sqli://hostip:port/dbname:informixserver=<dbservername> |
(3).總結
1.ADO.NET最大的優點是對斷開連接訪問數據庫方式的強有力支持。相比起來,JDBC也引入類似的功能,RowSet,但是比起ADO.NET來,還是不夠。
2.ADO.NET不包括分布式事務的接口,ADO.NET的分布式事務是通過MS DTC統一管理的。JDBC本身就提供了對分布式事務支持的接口,不同的JDBC Driver實現了這一個接口,就支持分布式事務了。
3.ADO.NET中,不同的ADO .NET Provider的參數格式不一樣的。OleDb和Odbc都是使用匿名參數,SqlClient使用“@”開頭的命名參數,OracleCLient使用“:”開頭的命名參數
4.JDBC中,參數計數是從1開始的,最初使用者容易犯錯。ADO.NET沒有此問題
5.ADO.NET是從ODBC,JDBC,OLEDB 發展過來,而JDBC是ODBC的JAVA版本
6.ADO.NET封裝程度比較高,用起來很方便
2.DBHelper 和 DBUtils
DBHelper有動軟的SQLHelper,DbProviderFactory封裝的DBHelper,微軟EnterpriseLibary封裝的DBHelper
主要是封裝的ADO.NET的代碼,簡化dal層的操作
支持多種數據庫,需要自己反射把DataTable轉換成Model
Dbutils由Apache公司開發
主要是封裝了JDBC的代碼,簡化dao層的操作,有對象映射的功能。
支持多種數據庫,可以直接把數據轉換成Model
源碼預覽

1 public Boolean Register(TUser user) throws SQLException{ 2 Connection conn =JDBCUtil.getConnection(); 3 QueryRunner qr = new QueryRunner(); 4 String sql="insert into t_user(username,password,sex,birthdate,address) values(?,?,?,?,?)"; 5 6 try { 7 int i = qr.update(conn, sql,user.getUsername(),user.getPassword(),user.getSex(),user.getBirthdate(),user.getAddress()); 8 return i==1 ? true:false; 9 } catch (SQLException e) { 10 // TODO Auto-generated catch block 11 e.printStackTrace(); 12 } 13 finally{ 14 DbUtils.close(conn); 15 } 16 return false; 17 } 18 19 public List<TUser> findAll() throws SQLException{ 20 Connection conn =JDBCUtil.getConnection(); 21 QueryRunner qr = new QueryRunner(); 22 String sql = "select * from T_User"; 23 List<TUser> users = new ArrayList<TUser>(); 24 try { 25 users = qr.query(conn,sql, new BeanListHandler<TUser>(TUser.class)); 26 } catch (SQLException e) { 27 // TODO Auto-generated catch block 28 e.printStackTrace(); 29 } 30 finally{ 31 DbUtils.close(conn); 32 } 33 return users; 34 }
3.EF 和 Hibernate
(1).對象關系配制
EF支持Fluent API和Attribute方式
Hibernate支持XML和注解的方式
(2).Linq 和 HQL,Criteria 面向對象的查詢方法
Linq相比於HQL更強大,支持編譯時排錯,有智能提示;Criteria相當於Where,Select 等各種方法
(3).原生SQL支持
EF:context.Database.SqlQuery()
Hibernate:getSession().createSQLQuery()
(4).緩存
一級緩存:EF和Hibernate都默認支持一級緩存
二級緩存:Hibernate支持二級緩存,一般使用Nosql來代替二級緩存
(5).更新部分字段
EF:
先讓EF跟蹤實體,然后修改實體即可
EntityEntry<News> entry = cnotext.Entry<News>(news);
entry.State = EntityState.Unchanged;
entry.Property(t => t.xxxx).IsModified = true; //設置要更新的屬性
context.SaveChanges();
Hibernate:
1.使用HQL語句,因為實體字段沒有狀態
2.修改hbm的class 的dynamic-update="true",在dao先find出來,再修改保存,影響性能
(6).主從級聯保存
EF和Hibernate都支持主從級聯保存
(7).批量更新和刪除
ORM框架在批量數據處理的時候是有弱勢。
ORM是針對某一對象(單個對象)簡單的查\改\刪\增,不是批量修改、刪除,適合用ORM;而對於批量修改、刪除,不適合用ORM
EF:可以使用SQL實現批量更新和刪除,context.Database.ExecuteSqlCommand()
Hibernate:可以使用HQL實現批量更新和刪除,getSession().createQuery(hql).executeUpdate()
(8).附上封裝好的Hibernate BaseDao

package com.rabbit.dao.impl; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import org.hibernate.Hibernate; import org.hibernate.LockMode; import org.hibernate.SQLQuery; import org.hibernate.transform.Transformers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import com.rabbit.dao.BaseDao; import com.rabbit.dto.Pager; import com.rabbit.dto.QueryParam; public class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> { private Logger log = LoggerFactory .getLogger(this.getClass()); // 實體類類型(由構造方法自動賦值) private Class<T> entityClass; //實體類名(由構造方法自動賦值) private String entityName; // 構造方法,根據實例類自動獲取實體類類型 public BaseDaoImpl() { this.entityClass = null; Class c = getClass(); Type t = c.getGenericSuperclass(); if (t instanceof ParameterizedType) { Type[] p = ((ParameterizedType) t).getActualTypeArguments(); this.entityClass = (Class<T>) p[0]; this.entityName = entityClass.getSimpleName(); } } protected void initDao() { // do nothing } /* * 新增數據 */ /* (non-Javadoc) * @see com.rabbit.dao.impl.BaseDao#save(T) */ @Override public Integer save(T transientInstance) { log.debug("saving TCategory instance"); Integer key = null; try { key = (Integer)getHibernateTemplate().save(transientInstance); log.debug("save successful"); } catch (RuntimeException re) { log.error("save failed", re); throw re; } return key; } /* * 更新數據 */ /* (non-Javadoc) * @see com.rabbit.dao.impl.BaseDao#update(T) */ @Override public void update(T transientInstance) { log.debug("updating TCategory instance"); try { getHibernateTemplate().update(transientInstance); log.debug("update successful"); } catch (RuntimeException re) { log.error("update failed", re); throw re; } } /* * 刪除數據 */ /* (non-Javadoc) * @see com.rabbit.dao.impl.BaseDao#delete(T) */ @Override public void delete(T persistentInstance) { log.debug("deleting TCategory instance"); try { getHibernateTemplate().delete(persistentInstance); log.debug("delete successful"); } catch (RuntimeException re) { log.error("delete failed", re); throw re; } } /* * 根據id刪除數據 */ /* (non-Javadoc) * @see com.rabbit.dao.impl.BaseDao#deleteById(java.lang.Integer) */ @Override public void deleteById(Integer id) { log.debug("deleting TCategory instance"); try { T instance = (T) findById(id); getHibernateTemplate().delete(instance); log.debug("delete successful"); } catch (RuntimeException re) { log.error("delete failed", re); throw re; } } /* * 合並數據,必須有id,會先select查出數據 */ /* (non-Javadoc) * @see com.rabbit.dao.impl.BaseDao#merge(T) */ @Override public T merge(T detachedInstance) { log.debug("merging TCategory instance"); try { T result = (T) getHibernateTemplate().merge( detachedInstance); log.debug("merge successful"); return result; } catch (RuntimeException re) { log.error("merge failed", re); throw re; } } /* * 更新數據,有id就更新數據,沒有就新增 */ /* (non-Javadoc) * @see com.rabbit.dao.impl.BaseDao#saveOrUpdate(T) */ @Override public void saveOrUpdate(T instance) { log.debug("attaching dirty TCategory instance"); try { getHibernateTemplate().saveOrUpdate(instance); log.debug("attach successful"); } catch (RuntimeException re) { log.error("attach failed", re); throw re; } } /* * 根據id查詢數據 */ /* (non-Javadoc) * @see com.rabbit.dao.impl.BaseDao#findById(java.lang.Integer) */ @Override public T findById(Integer id) { log.debug("getting TCategory instance with id: " + id); try { T instance = (T) getHibernateTemplate().get(entityClass, id); return instance; } catch (RuntimeException re) { log.error("get failed", re); throw re; } } /* * 根據Model查詢數據 */ /* (non-Javadoc) * @see com.rabbit.dao.impl.BaseDao#findByExample(T) */ @Override public List findByExample(T instance) { log.debug("finding TCategory instance by example"); try { List results = getHibernateTemplate().findByExample(instance); log.debug("find by example successful, result size: " + results.size()); return results; } catch (RuntimeException re) { log.error("find by example failed", re); throw re; } } /* * 根據屬性查詢 */ /* (non-Javadoc) * @see com.rabbit.dao.impl.BaseDao#findByProperty(java.lang.String, java.lang.Object) */ @Override public List findByProperty(String propertyName, Object value) { log.debug("finding TCategory instance with property: " + propertyName + ", value: " + value); try { String queryString = "from "+ entityName +" as model where model." + propertyName + "= ?"; return getHibernateTemplate().find(queryString, value); } catch (RuntimeException re) { log.error("find by property name failed", re); throw re; } } /* * 根據HQL where查詢 */ /* (non-Javadoc) * @see com.rabbit.dao.impl.BaseDao#findByHQL(java.lang.String, java.lang.Object) */ @Override public List findByHQL(String where,Object... para){ log.debug("finding all TUser instances"); try { String queryString = "from "+ entityClass.getSimpleName() +" "+ where; return getHibernateTemplate().find(queryString,para); } catch (RuntimeException re) { log.error("find all failed", re); throw re; } } /* * 根據SQL查詢分頁 */ /* (non-Javadoc) * @see com.rabbit.dao.BaseDao#findBySQL(java.lang.Class, java.lang.String, QueryParam) */ @Override public <DTO> Pager<DTO> findBySQL(Class<DTO> type,String sql,QueryParam param) { log.debug("finding all TUser instances"); try { //外層包裝sql String outerSql = "Select %s from (%s) pager"; String countSql = String.format(outerSql, "Count(1) cnt",sql); SQLQuery countQuery = getSession().createSQLQuery(countSql); Object[] para = param.getPara(); //填充參數 preparePara(countQuery,para); countQuery.addScalar("cnt",Hibernate.INTEGER); Integer count = (Integer)countQuery.uniqueResult(); Pager<DTO> pager = new Pager<DTO>(); pager.InitPager(param.getPageIndex(), param.getPageSize(), count); List<DTO> items = new ArrayList<DTO>(); if(param.getPageIndex()<=pager.getTotalPage()){ //設置排序 if(param.getOrderBy()!=null){ sql=sql+" order by " + param.getOrderBy(); } SQLQuery query = getSession().createSQLQuery(String.format(outerSql, "*",sql)); //填充參數 preparePara(query,para); //轉換成dto query.setResultTransformer(Transformers.aliasToBean(type)); //設置分頁 query.setFirstResult(param.getPageOffset()); query.setMaxResults(param.getPageSize()); items = query.list(); } pager.setItems(items); return pager; } catch (RuntimeException re) { log.error("find all failed", re); throw re; } } /* * 准備Query參數 */ private void preparePara(SQLQuery query,Object[] para){ if(para!=null){ for(int i=0;i<para.length;i++){ query.setParameter(i, para[i]); } } } /* * 准備Query參數 */ private void preparePara(SQLQuery query,Map<String,Object> para){ if(para!=null && !para.isEmpty()){ for(String key : para.keySet()){ Object obj = para.get(key); if (obj instanceof Collection<?>) query.setParameterList(key, (Collection<?>) obj); else if (obj instanceof Object[]) query.setParameterList(key, (Object[]) obj); else query.setParameter(key, obj); } } } /* * 查詢所有數據 */ /* (non-Javadoc) * @see com.rabbit.dao.impl.BaseDao#findAll() */ @Override public List findAll() { log.debug("finding all TCategory instances"); try { String queryString = "from "+entityClass.getSimpleName(); return getHibernateTemplate().find(queryString); } catch (RuntimeException re) { log.error("find all failed", re); throw re; } } }
(9).源碼下載
4.擴展閱讀
update 和 merge、saveOrUpdate的區別
Dapper和Mybatis的比較放在下一篇吧,也許直接到微服務篇了
時間倉促,很多東西沒有寫到,歡迎大家指點
未完,待續,歡迎評論拍磚