1.注解
package com.seesource.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Column { /** * 映射在数据表中的字段名 * @return */ public String value() default ""; }
package com.seesource.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 主键标识 * @author Administrator * */ @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Id { }
package com.seesource.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 主键生成策略 * @author Administrator * */ @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Strategy { int value() default StrategyType.INCREMENT; }
package com.seesource.annotation; public interface StrategyType { int ASSIGNED = 0; //由程序提供 int INCREMENT = 1; //自增(不需要提供) }
package com.seesource.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Table { /** * 映射到数据库中的数据表名 * @return */ public String value() default ""; }
dao实现
package com.seesource.dao; import java.sql.SQLException; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; public interface DataSourceFactory { public DataSource createDataSource(); }
package com.seesource.dao; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.sql.Connection; import java.sql.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.sql.Timestamp; import java.util.ArrayList; import java.util.List; import javax.naming.NamingException; import com.seesource.annotation.Column; import com.seesource.annotation.Id; import com.seesource.annotation.Strategy; import com.seesource.annotation.StrategyType; import com.seesource.annotation.Table; import com.seesource.exception.NotDefineColumnException; import com.seesource.exception.NotDefinePrimaryKeyException; import com.seesource.exception.NotDefineTableException; public class GenericDao<T> { private Class clazz; private String table;//数据库表名 private ColumnItem id;//主键字段名 private int strategy = StrategyType.INCREMENT;//主键生成策略 //String:字段名 Field:相应的实体get方法 private List<ColumnItem> columns = new ArrayList<ColumnItem>(); private static ThreadLocal tansaction_connecton_map = new ThreadLocal(); private DataSourceFactory dataSourceFactory; /** * 获得参数T的实际类型 * @return */ private Class getGenericType() { Class clazz = getClass(); Type genType = clazz.getGenericSuperclass(); Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); return (Class) params[0]; } /** * 初始化 */ public void init()throws NotDefineTableException,NotDefineColumnException,NotDefinePrimaryKeyException,Exception{ Class clazz = getGenericType(); this.clazz = clazz; Table ta = (Table)clazz.getAnnotation(Table.class); if(ta == null || ta.value().trim().equals("")) throw new NotDefineTableException(this.clazz.toString() + "----未设置表名!"); this.table = ta.value(); for (Field f : clazz.getDeclaredFields()) { Column anno = f.getAnnotation(Column.class); if (anno != null) { String columnName = anno.value(); if(columnName == null || columnName.trim().equals("")) throw new NotDefineColumnException(f.getName() + "----未设置字段名!"); ColumnItem column = new ColumnItem(columnName, f, new PropertyDescriptor(f.getName(), this.clazz)); //判断是否是主键 Id idAnno = f.getAnnotation(Id.class); if(idAnno != null){ this.id = column; //获得主键 Strategy strategyAnno = f.getAnnotation(Strategy.class); if(strategyAnno != null)//获得主键生成策略 this.strategy = strategyAnno.value(); continue; } columns.add(column); }else{ throw new NotDefineColumnException(f.getName() + "----未设置字段名!"); } } if(this.id == null) throw new NotDefinePrimaryKeyException(this.clazz.toString() + "----未设置主键!"); } /** * 添加记录 * @param rec * @return * @throws SQLException */ public int save(T entity) throws Exception { List<Object> params = new ArrayList<Object>(); StringBuffer sb = new StringBuffer("INSERT INTO "); StringBuffer sb_values = new StringBuffer(); sb.append(this.table); sb.append(" ("); if(this.strategy == StrategyType.ASSIGNED){ PropertyDescriptor pd = this.id.propertyDescriptor; Method getMethod = pd.getReadMethod(); Object value = getMethod.invoke(entity); sb.append(this.id.columnName); sb.append(","); sb_values.append("?,"); params.add(value); } for (ColumnItem entry : columns) { PropertyDescriptor pd = entry.propertyDescriptor; Method getMethod = pd.getReadMethod(); Object value = getMethod.invoke(entity); if(value == null)//不对空值进行操作 continue; sb.append(entry.columnName); sb.append(","); params.add(value); sb_values.append("?,"); } sb.deleteCharAt(sb.length() - 1); sb_values.deleteCharAt(sb_values.length() - 1); sb.append(") VALUES ("); sb.append(sb_values.toString()); sb.append(')'); Connection con = null; PreparedStatement stmt = null; con = getConnection(); stmt = con.prepareStatement(sb.toString()); setParams(stmt, params.toArray()); int nums = stmt.executeUpdate(); //返回受影响的行数 closeStatement(stmt); closeConnection(con); return nums; } /** * 修改 * @param sql * @param params * @return */ public int update(T entity) throws Exception { StringBuilder sb = new StringBuilder("UPDATE "); sb.append(this.table); sb.append(" SET "); List<Object> paramList = new ArrayList<Object>(); for (ColumnItem entry : columns) { Field field = entry.theField; PropertyDescriptor pd = entry.propertyDescriptor; Method getMethod = pd.getReadMethod(); Object value = getMethod.invoke(entity); sb.append(entry.columnName); sb.append(" = ?,"); paramList.add(value); } sb.deleteCharAt(sb.length() - 1); sb.append(" WHERE "); sb.append(this.id.columnName); sb.append(" = ?"); PropertyDescriptor pd = this.id.propertyDescriptor; Method getMethod = pd.getReadMethod(); Object value = getMethod.invoke(entity); paramList.add(value); Connection con = null; PreparedStatement stmt = null; con = getConnection(); stmt = con.prepareStatement(sb.toString()); setParams(stmt, paramList.toArray()); int nums = stmt.executeUpdate(); //返回受影响的行数 closeStatement(stmt); closeConnection(con); return nums; } /** * 删除 * @param sql * @param params * @return */ public int delete(T entity) throws Exception { StringBuilder sb = new StringBuilder("delete from "); sb.append(this.table); sb.append(" where "); sb.append(this.id.columnName); sb.append(" = ?"); PropertyDescriptor pd = this.id.propertyDescriptor; Method getMethod = pd.getReadMethod(); Object value = getMethod.invoke(entity); Object[] params = new Object[1]; params[0] = value; Connection con = null; PreparedStatement stmt = null; con = getConnection(); stmt = con.prepareStatement(sb.toString()); setParams(stmt, params); int nums = stmt.executeUpdate(); //返回受影响的行数 closeStatement(stmt); closeConnection(con); return nums; } /** * 查询 * @param sql * @param params * @return */ public List<T> find(String sql, Object[] params){ List<T> list = new ArrayList<T>(); Connection con = null; PreparedStatement stmt = null; ResultSet rs = null; try { con = this.getConnection(); stmt = con.prepareStatement(sql); setParams(stmt, params); rs = stmt.executeQuery(); ResultSetMetaData rsmd = rs.getMetaData(); int columnCount = rsmd.getColumnCount(); while(rs != null && rs.next()){ T entity = (T)this.clazz.newInstance(); for(int i = 0; i<columnCount; i++){ String columnName = rsmd.getColumnName(i+1); ColumnItem columnItem = getColumnItem(columnName); if(columnItem != null){ PropertyDescriptor pd = columnItem.propertyDescriptor; Method setMethod = pd.getWriteMethod(); Object value = rs.getObject(columnName); setMethod.invoke(entity, value); } } list.add(entity); } }catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ closeResultSet(rs); closeStatement(stmt); closeConnection(con); } return list; } /** * 通过主键获得单个实例 * 如果库中无此实例,则返回null * @param entity * @return */ public T get(T entity)throws Exception{ StringBuffer sb = new StringBuffer("select * from "); sb.append(this.table); sb.append(" where "); sb.append(this.id.columnName); sb.append(" = ?"); PropertyDescriptor pd = this.id.propertyDescriptor; Method getMethod = pd.getReadMethod(); Object id_value = getMethod.invoke(entity); Object[] params = new Object[1]; params[0] = id_value; Connection con = null; PreparedStatement stmt = null; ResultSet rs = null; try { con = this.getConnection(); stmt = con.prepareStatement(sb.toString()); setParams(stmt, params); rs = stmt.executeQuery(); ResultSetMetaData rsmd = rs.getMetaData(); int columnCount = rsmd.getColumnCount(); if(rs != null && rs.next()){ for(int i = 0; i<columnCount; i++){ String columnName = rsmd.getColumnName(i+1); ColumnItem columnItem = getColumnItem(columnName); if(columnItem != null){ pd = columnItem.propertyDescriptor; Method setMethod = pd.getWriteMethod(); Object value = rs.getObject(columnName); setMethod.invoke(entity, value); } } return entity; } }catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ closeResultSet(rs); closeStatement(stmt); closeConnection(con); } return null; } /** * 统计数量 * @param sql * @param params * @return */ public long count(String sql, Object[] params){ long count = 0; Connection con = null; PreparedStatement stmt = null; ResultSet rs = null; try { con = this.getConnection(); stmt = con.prepareStatement(sql); setParams(stmt, params); rs = stmt.executeQuery(); if(rs != null && rs.next()){ count = rs.getLong(1); } }catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ closeResultSet(rs); closeStatement(stmt); closeConnection(con); } return count; } /** * 判断实体注解配置中是否有此字段 * @param columnName * @return */ private ColumnItem getColumnItem(String columnName){ if(this.id.columnName.equals(columnName)) return this.id; for(int i = 0; i<this.columns.size(); i++){ ColumnItem item = this.columns.get(i); if(columnName.equals(item.columnName)) return item; } return null; } /** * 关闭ResultSet * @param rs */ protected void closeResultSet(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 关闭Statement * @param stmt */ protected void closeStatement(Statement stmt){ try { if(stmt != null){ stmt.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 归还连接 * @param con */ public void closeConnection(Connection con){ try { Object obj = tansaction_connecton_map.get(); if(obj == null && con != null){ //不在事务控制中时直接关闭 con.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 开启事务 * @return */ public void startTransaction()throws SQLException,NamingException{ Connection con = createConnection(); con.setAutoCommit(false); tansaction_connecton_map.set(con); } /** * 提交事务 * @return */ public void commit()throws SQLException{ Object obj = tansaction_connecton_map.get(); if(obj != null){ Connection con = (Connection)obj; con.commit(); } } /** * 回滚事务 * @return */ public void rollback(){ try { Object obj = tansaction_connecton_map.get(); if(obj != null){ Connection con = (Connection)obj; con.rollback(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 销毁事务,释放连接 * @return * @throws SQLException * @throws NamingException */ public void distroyTransaction(){ try { Object obj = tansaction_connecton_map.get(); if(obj != null){ Connection con = (Connection)obj; con.setAutoCommit(true); con.close(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ tansaction_connecton_map.set(null); } } private Connection createConnection() throws SQLException, NamingException{ Connection con = this.dataSourceFactory.createDataSource().getConnection(); return con; } /** * 获得数据库连接 * @return * @throws SQLException * @throws NamingException */ public Connection getConnection() throws SQLException, NamingException{ Connection con = null; Object obj = tansaction_connecton_map.get(); if(obj != null){ con = (Connection)obj; }else{ con = createConnection(); } return con; } /** * 设置参数 * @param stmt * @param params * @throws SQLException */ protected void setParams(PreparedStatement stmt, Object[] params) throws SQLException{ for(int i = 0; i<params.length;){//int, short, long, float, double, boolean, byte, char, List if(params[i] == null){ stmt.setObject(i+1, null); i++; continue; } if(params[i] instanceof String){ stmt.setString(i+1, (String)params[i]); i++; continue; } if(params[i] instanceof Integer){ stmt.setInt(i+1, (Integer)params[i]); i++; continue; } if(params[i] instanceof Short){ stmt.setShort(i+1, (Short)params[i]); i++; continue; } if(params[i] instanceof Long){ stmt.setLong(i+1, (Long)params[i]); i++; continue; } if(params[i] instanceof Float){ stmt.setFloat(i+1, (Float)params[i]); i++; continue; } if(params[i] instanceof Double){ stmt.setDouble(i+1, (Double)params[i]); i++; continue; } if(params[i] instanceof Date){ stmt.setDate(i+1, (Date)params[i]); i++; continue; } if(params[i] instanceof Timestamp){ stmt.setTimestamp(i+1, (Timestamp)params[i]); i++; continue; } if(params[i] instanceof Boolean){ stmt.setBoolean(i+1, (Boolean)params[i]); i++; continue; } if(params[i] instanceof Byte){ stmt.setByte(i+1, (Byte)params[i]); i++; continue; } } } public void setDataSourceFactory(DataSourceFactory dataSourceFactory) { this.dataSourceFactory = dataSourceFactory; } class ColumnItem{ public ColumnItem(String columnName, Field theField, PropertyDescriptor propertyDescriptor){ this.columnName = columnName; this.theField = theField; this.propertyDescriptor = propertyDescriptor; } String columnName; Field theField; PropertyDescriptor propertyDescriptor; } }
exception实现
package com.seesource.exception; public class NotDefineColumnException extends Exception{ public NotDefineColumnException(){ super("未设置字段名!"); } public NotDefineColumnException(String msg){ super(msg); } }
package com.seesource.exception; /** * 未定义主键异常 * @author Administrator * */ public class NotDefinePrimaryKeyException extends Exception{ public NotDefinePrimaryKeyException(){ super("未定义主键"); } public NotDefinePrimaryKeyException(String msg){ super(msg); } }
package com.seesource.exception; public class NotDefineTableException extends Exception{ public NotDefineTableException(){ super("未设置表名!"); } public NotDefineTableException(String msg){ super(msg); } }
如何使用:
package com.seesource.persist; import java.sql.Date; import java.sql.Timestamp; import com.seesource.annotation.Column; import com.seesource.annotation.Id; import com.seesource.annotation.Strategy; import com.seesource.annotation.StrategyType; import com.seesource.annotation.Table; @Table("user") public class User { @Column("id_") @Id @Strategy(StrategyType.INCREMENT) private int id; @Column("name_") private String name; @Column("date_") private Timestamp date; public Timestamp getDate() { return date; } public void setDate(Timestamp date) { this.date = date; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
package com.seesource.dao; import com.seesource.persist.User; public class UserDao extends GenericDao<User>{ }
import java.sql.SQLException; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; import com.seesource.dao.DataSourceFactory; public class MyDataSourceFactory implements DataSourceFactory{ private DataSource dataSource; public MyDataSourceFactory()throws SQLException, NamingException{ Context initContext = new InitialContext(); Context envContext = (Context)initContext.lookup("java:/comp/env"); DataSource ds = (DataSource)envContext.lookup("jdbc/xinwei"); this.dataSource = ds; System.out.println("------------------------------已经创建了dataSource-----------------------------------------"); } public DataSource createDataSource(){ return this.dataSource; } }
场景1(增加记录)
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { UserDao dao = new UserDao(); DataSourceFactory dataSource = new MyDataSourceFactory(); dao.setDataSourceFactory(dataSource); dao.init(); User entity = new User(); entity.setName("张三"); entity.setDate(new java.sql.Timestamp(new java.util.Date().getTime())); dao.save(entity); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
场景2(查询)
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { UserDao dao = new UserDao(); DataSourceFactory dataSource = new MyDataSourceFactory(); dao.setDataSourceFactory(dataSource); dao.init(); String sql = "select * from user"; List<User> users = dao.find(sql, new Object[0]); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
场景3(业务级事务)
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { UserDao dao = new UserDao(); try { DataSourceFactory dataSource = new MyDataSourceFactory(); dao.setDataSourceFactory(dataSource); dao.init(); dao.startTransaction();//开始事务 User entity = new User(); entity.setId(8); entity.setName("张三"); entity.setDate(new java.sql.Timestamp(new java.util.Date().getTime())); int rat = dao.update(entity); if(rat == 0){ dao.rollback(); }else{ rat = dao.delete(entity); if(rat == 0){ dao.rollback(); }else{ dao.commit();//提交事务 } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); dao.rollback(); }finally{ dao.distroyTransaction();//销毁事务 } }