从零实现MVC框架之增删改查(4)

来源:互联网 发布:买家怎么进淘宝试衣间 编辑:程序博客网 时间:2024/05/16 15:57

概述

这一章节貌似有点小复杂。为了实现对象的增删改查,我们需要做点功课

1:生成id,我们采用手动生成id的方法,这里我们特意也为id创建了一个池子,所有的id都从池子里面取。

2:对象状态: 新建状态、持久状态、查询状态。查询状态是内部处理。

      处于新建状态下的对象可以进行保存操作,不能更新和删除
      处于持久状态下的对象可以进行更新和删除操作,不能保存。

3:执行器:我们所有的sql的执行都要靠执行器执行并返回结构。

4:数据装配:处理sql中的占位符以及返回结果的处理。

5:事务:提交和回滚。我们这里只是提供了这个方法,但是还没有具体实现。因为我们现在的连接都是自动提交的不涉及到事务问题。等到后面章节我们做AOP事务管理的时候会具体实现。


实现思路

为了简单起见,我们把增删改查方法都定义到实体类上。通过继承AbstractEntity可以继承这些方法。不过具体实体类不用实现这些方法。每个实体类在进行每次增删该查方法时,都会重新获取一个执行器,然后通过执行器执行sql。执行器也在AbstractEntity中创建。下面看具体代码:

 

实体类:

接口

package com.hc.core;import java.sql.SQLException;/** * 实体接口 所有数据库实体都必须实现这个接口 * @author chuer * @date 2014-7-16 下午12:07:47 * @version V1.0 */public interface IEntity {public long getId();//获得实体主键public void setId(long id);//设置实体主键public void persist() throws SQLException;//增public void remove() throws SQLException;//删public IEntity get(long id) throws SQLException;//查public void update(String columnName) throws SQLException;//改public void setExecute();//设置执行器public void rollBack();}


抽象实现

package com.hc.core;import java.sql.SQLException;/** * 抽象实体类 * @author chuer * @date 2014-7-16 下午12:08:42 * @version V1.0 */public abstract class AbstractEntity implements IEntity {protected AbstractExecute<AbstractEntity> execute;protected EntityStatus status;public AbstractEntity(){this.status = EntityStatus.NEW;//状态为新建}@Overridepublic void persist() throws SQLException {//持久化对象 只有新建的对象才可以进行持久化if(this.status == EntityStatus.NEW){setExecute();try{execute.save(this);}catch(SQLException e){rollBack();throw e;}this.status = EntityStatus.PERSIST;}}@Overridepublic void remove() throws SQLException{//删除用户  只有持久化的对象才可以进行删除操作if(this.status == EntityStatus.PERSIST){setExecute();try {execute.delete(this);} catch (SQLException e) {rollBack();throw e;}this.status = EntityStatus.NEW;}}@Overridepublic  AbstractEntity get(long id) throws SQLException {this.setId(id);this.status = EntityStatus.QUERY;setExecute();execute.get(this);this.status = EntityStatus.PERSIST;return this;}@Overridepublic void update(String columnName) throws SQLException{//只有持久化对象才能进行更新操作if(this.status == EntityStatus.PERSIST){setExecute();try{execute.update(this, columnName);}catch(SQLException e){rollBack();throw e;}}}public EntityStatus getStatus() {return status;}public void setStatus(EntityStatus status) {this.status = status;}@Overridepublic void setExecute() {execute = ExecuteFactory.getExecute();}@Overridepublic void rollBack() {}}

具体实现

package com.hc.sample.entity;import java.sql.SQLException;import com.hc.annotation.Column;import com.hc.annotation.Entity;import com.hc.core.AbstractEntity;/** *  * @author chuer * @date 2014-7-16 上午9:33:02 * @version V1.0 */@Entity(entityName="UserEntity",tableName="user_m")public class UserEntity  extends AbstractEntity{public UserEntity(){super();}@Column(type=long.class,name="id",isPrimary=true)private long id;@Column(type=String.class,name="name")private String name;public long getId() {return id;}public void setId(long id) {this.id = id;}public String getName() {return name;}public void setName(String name) throws SQLException {this.name = name;//更新数据到数据库 只有持久化的数据才可以更新操作update("name");}}


ID生成

生成器

package com.hc.utils;import java.util.Date;/** * id生成 * @author chuer * @version 2014-7-16  上午11:38:34 */public class UID {private static Date date = new Date();private static StringBuilder buf = new StringBuilder();private static int seq = 0;private static final int ROTATION = 99999;public static synchronized long next() {if (seq > ROTATION)seq = 0;buf.delete(0, buf.length());date.setTime(System.currentTimeMillis());String str = String.format("%1$tY%1$tm%1$td%1$tk%1$tM%1$tS%2$05d",date, seq++);return Long.parseLong(str);}public static void main(String ...args){new MyThread().start();new MyThread().start();new MyThread().start();new MyThread().start();new MyThread().start();new MyThread().start();new MyThread().start();new MyThread().start();new MyThread().start();new MyThread().start();}}class MyThread extends Thread{@Overridepublic void run() {for(int i=0;i<100;i++){System.out.println(UID.next());}}}


ID池

package com.hc.pool;import java.util.concurrent.ConcurrentLinkedQueue;import com.hc.utils.UID;/** * id池子 * @author chuer * @version 2014-7-16  下午12:23:26 */public class IDPool {private static final int MAX_POOL_SIZE = 100000;//id池大小private static final int MIN_POOL_SIZE = 100;//id池大小private static volatile boolean isInit = false;private IDPool(){}private static IDPool pool = new IDPool();private ConcurrentLinkedQueue<Long> pools = new ConcurrentLinkedQueue<Long>();public static IDPool getInstance(){if(!isInit){isInit = true;pool.startGenerateId();}return pool;}public void  startGenerateId(){GenerateId gi = new GenerateId();new Thread(gi).start();}void addId(Long id){pools.add(id);}public Long applyId(){Long id = pools.poll();if(id == null){return UID.next();}return id;}class GenerateId implements Runnable{@Overridepublic void run() {while(true){if(pools.size()<MIN_POOL_SIZE){while(true){addId(UID.next());if(pools.size() == MAX_POOL_SIZE){break;}}}try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}}}}


执行器

接口

package com.hc.core;import java.sql.Connection;import java.sql.SQLException;import java.util.Collection;/** * 增删改差接口  执行器 * @author chuer * @date 2014-7-16 上午10:08:17 * @version V1.0 */public interface IExecute<T> {public int save(T t) throws SQLException;  //保存操作public int update(T t, String column) throws SQLException;  //更新操作public int delete(T t) throws SQLException; //删除操作public T get(T t) throws SQLException; //单个查询操作public Collection<T> query(Class<T> cls,String sql)throws SQLException;//批量查询操作public void execute(String sql) throws SQLException;//执行自定义sqlpublic void relase(Connection conn);//释放连接public void setAutoCommit(boolean autoCommit);//设置连接是否自动提交}

 

package com.hc.core;/** * 事务提交接口 * @author chuer * @version 2014-7-16  上午11:27:24 */public interface ICommit {public void commit();//提交public void rollback();//回滚}


抽象实现

package com.hc.core;import java.sql.Connection;import java.sql.SQLException;import java.sql.Statement;import com.hc.pool.DBConfig;import com.hc.pool.DBPool;/** * 抽象执行器 * @author chuer * @date 2014-7-16 上午10:08:51 * @version V1.0 */public abstract class AbstractExecute<T> implements  IExecute<T>,ICommit{protected Connection conn;protected boolean autoCommit;protected AbstractExecute(Connection conn){this.conn = conn;this.autoCommit = DBConfig.AUTOCOMMIT;}@Overridepublic void commit() {try {conn.commit();relase(conn);} catch (SQLException e) {e.printStackTrace();}}@Overridepublic void rollback() {try {conn.rollback();} catch (SQLException e) {e.printStackTrace();}}@Overridepublic void relase(Connection conn) {DBPool.getInstance().relaseConnection(conn);}@Overridepublic void execute(String sql) throws SQLException {System.out.println(sql);Statement stat = conn.createStatement();stat.execute(sql);if(autoCommit){commit();}}@Overridepublic void setAutoCommit(boolean autoCommit1) {autoCommit = autoCommit1;}}


 

具体实现

package com.hc.execute;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.ArrayList;import java.util.Collection;import com.hc.cache.CacheManager;import com.hc.core.AbstractExecute;import com.hc.core.IEntity;import com.hc.sql.SqlManager;import com.hc.utils.AssembleData;import com.hc.utils.AssembleStatement;/** * 执行器实现类 * @author chuer * @version 2014-7-16  上午11:36:08 * @param <T> */public class ExecuteImpl<T extends IEntity> extends AbstractExecute<T>{public ExecuteImpl(Connection conn){super(conn);}@Overridepublic int save(T t) throws SQLException {String insertSql = SqlManager.getInstance().getInsertSql(t.getClass());System.out.println(insertSql);PreparedStatement stat = AssembleStatement.assembleInsertSql(t, insertSql, conn);stat.execute();if(autoCommit){commit();}CacheManager.cache(t);return 0;}@Overridepublic int update(T t,String column) throws SQLException {String updateSql = SqlManager.getInstance().getUpdateSql(t.getClass(),column);System.out.println(updateSql);PreparedStatement stat = AssembleStatement.assembleUpdateSql(t, updateSql, conn, column);stat.execute();if(autoCommit){commit();}return 0;}@Overridepublic int delete(T t) throws SQLException {String deleteSql = SqlManager.getInstance().getDeleteSql(t.getClass());System.out.println(deleteSql);PreparedStatement stat = AssembleStatement.assembleDeleteSql(t, deleteSql, conn);stat.execute();if(autoCommit){commit();}return 0;}@Overridepublic T get(T t) throws SQLException {String singleSql = SqlManager.getInstance().getSingleSql(t.getClass());System.out.println(singleSql);PreparedStatement stat = AssembleStatement.assembleSingleSql(t, singleSql, conn);ResultSet rs = stat.executeQuery();try {AssembleData.assembleSingle(t, rs);} catch (Exception e) {e.printStackTrace();}if(autoCommit){commit();}return t;}@Overridepublic Collection<T> query(Class<T> cls,String condition)throws SQLException {String querySql = SqlManager.getInstance().getQuerySql(cls);querySql += condition;System.out.println(querySql);Statement stat = conn.createStatement();ResultSet rs = stat.executeQuery(querySql);Collection<T> list = null;try {list = AssembleData.assembleCollection(new ArrayList<T>(), cls, rs);} catch (Exception e) {e.printStackTrace();}if(autoCommit){commit();}return list;}}


 

装配器:

package com.hc.utils;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;import com.hc.annotation.Column;/** * sql装配 * @author chuer * @version 2014-7-16  上午10:13:05 */public class AssembleStatement {/** * 装配单个查询sql * @param t * @param sql * @param conn * @return */public static <T> PreparedStatement assembleSingleSql(T t,String sql,Connection conn){try{PreparedStatement pStat= conn.prepareStatement(sql);Field[] fields = t.getClass().getDeclaredFields();for(Field fie : fields){if(fie.isAnnotationPresent(Column.class)){Column annotation = fie.getAnnotation(Column.class);if(annotation.isPrimary()){Object id = getColumnValue(fie.getName(), t);fill(annotation,pStat,1,id);break;}}}return pStat;}catch(Exception e){e.printStackTrace();}return null;}/** * 装配删除sql * @param t * @param sql * @param conn * @return */public static <T> PreparedStatement assembleDeleteSql(T t,String sql,Connection conn){try{PreparedStatement pStat= conn.prepareStatement(sql);Field[] fields = t.getClass().getDeclaredFields();for(Field fie : fields){if(fie.isAnnotationPresent(Column.class)){Column annotation = fie.getAnnotation(Column.class);if(annotation.isPrimary()){Object id = getColumnValue(fie.getName(), t);fill(annotation,pStat,1,id);break;}}}return pStat;}catch(Exception e){e.printStackTrace();}return null;}/** * 装配更新sql * @param t * @param sql * @param conn * @param columnName * @return */public static <T> PreparedStatement assembleUpdateSql(T t,String sql,Connection conn,String columnName){try{PreparedStatement pStat= conn.prepareStatement(sql);Object value = getColumnValue(columnName, t);Field field = t.getClass().getDeclaredField(columnName);fill(field.getAnnotation(Column.class),pStat,1,value);Field[] fields = t.getClass().getDeclaredFields();for(Field fie : fields){if(fie.isAnnotationPresent(Column.class)){Column annotation = fie.getAnnotation(Column.class);if(annotation.isPrimary()){Object id = getColumnValue(fie.getName(), t);fill(annotation,pStat,2,id);break;}}}return pStat;}catch(Exception e){e.printStackTrace();}return null;}/** * 装配插入sql * @param t * @param sql * @param conn * @return * @throws SQLException */public static <T> PreparedStatement assembleInsertSql(T t,String sql,Connection conn)throws SQLException{try{PreparedStatement pStat= conn.prepareStatement(sql);Field [] fileds = t.getClass().getDeclaredFields();for(int i=0;i<fileds.length;i++){Field field = fileds[i];if(field.isAnnotationPresent(Column.class)){Object value = getColumnValue(field.getName(),t);fill(field.getAnnotation(Column.class),pStat,i+1,value);}}return pStat;}catch(Exception e){e.printStackTrace();}return null;}/** * 得到字段的值 * @param columnName * @param t * @return * @throws Exception */private static <T>  Object getColumnValue(String columnName,T t)throws Exception{String methodName = "get"+columnName.substring(0,1).toUpperCase()+columnName.substring(1, columnName.length());Method method = t.getClass().getMethod(methodName, new Class[]{});Object value = method.invoke(t, new Object[]{});return value;}/** * 替换sql中的? * @param ctype * @param pStat * @param index * @param value * @throws Exception */private static void fill(Column ctype,PreparedStatement pStat,int index,Object value)throws Exception{Class<? extends Object> type = ctype.type();if(type == int.class){pStat.setInt(index, (int)value);}else if(type == byte.class){pStat.setByte(index, (byte)value);}else if(type == short.class){pStat.setShort(index, (short)value);}else if(type == long.class){pStat.setLong(index, (long)value);}else if(type == String.class){pStat.setString(index, (String)value);}}}


 

package com.hc.utils;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.sql.ResultSet;import java.util.Collection;import com.hc.annotation.Column;import com.hc.core.EntityStatus;public class AssembleData {/** * 返回集合 * @param list * @param cls * @param rs * @return * @throws Exception */public static <T> Collection<T> assembleCollection(Collection<T> list,Class<T> cls,ResultSet rs)throws Exception{while(rs.next()){T instance = cls.getConstructor(new Class[]{}).newInstance(new Object[]{});assemble(instance,rs);list.add(instance);}return list;}private  static <T> T assemble(T t,ResultSet rs) throws Exception{Method method = t.getClass().getMethod("setStatus", new Class[]{EntityStatus.class});method.invoke(t, new Object[]{EntityStatus.QUERY});Field[] declaredFields = t.getClass().getDeclaredFields();for(Field field : declaredFields){if(field.isAnnotationPresent(Column.class)){Column annotation = field.getAnnotation(Column.class);String fieldName = field.getName();String ColumnName = annotation.name();Class<?> type = annotation.type();setValue(t,type,rs,ColumnName,fieldName);}}method.invoke(t, new Object[]{EntityStatus.PERSIST});return t;}/** * 返回单对象 * @param t * @param rs * @return * @throws Exception */public static <T> T assembleSingle(T t,ResultSet rs) throws Exception{if(rs.next()){Field[] declaredFields = t.getClass().getDeclaredFields();for(Field field : declaredFields){if(field.isAnnotationPresent(Column.class)){Column annotation = field.getAnnotation(Column.class);String fieldName = field.getName();String ColumnName = annotation.name();Class<?> type = annotation.type();setValue(t,type,rs,ColumnName,fieldName);}}}return t;}private static <T,S> void setValue(T t,Class<S> type,ResultSet rs,String columnName,String fieldName)throws Exception{String setMethodName = "set"+fieldName.substring(0, 1).toUpperCase()+fieldName.substring(1);Method setMethod = t.getClass().getMethod(setMethodName, new Class[]{type});if(type == int.class){setMethod.invoke(t, new Object[]{rs.getInt(columnName)});}else if(type == byte.class){setMethod.invoke(t, new Object[]{rs.getByte(columnName)});}else if(type == short.class){setMethod.invoke(t, new Object[]{rs.getShort(columnName)});}else if(type == long.class){setMethod.invoke(t, new Object[]{rs.getLong(columnName)});}else if(type == String.class){setMethod.invoke(t, new Object[]{rs.getString(columnName)});}}}


工具类Query

package com.hc.utils;import java.lang.reflect.InvocationTargetException;import java.sql.SQLException;import java.util.Collection;import com.hc.cache.CacheManager;import com.hc.core.AbstractExecute;import com.hc.core.ExecuteFactory;import com.hc.core.IEntity;public class Query {public static <T extends IEntity> Collection<T> query(Class<T> cls,String condition) throws SQLException{AbstractExecute<T> execute = ExecuteFactory.getExecute();return execute.query(cls, condition);}public static IEntity load(Class<?> cls,long id) throws SQLException {IEntity entity = CacheManager.getEntity(cls.toString()+id);if(entity != null){return entity;}IEntity newInstance = null;try {newInstance = (IEntity)cls.getConstructor(new Class[]{}).newInstance(new Object[]{});} catch (InstantiationException | IllegalAccessException| IllegalArgumentException | InvocationTargetException| NoSuchMethodException | SecurityException e) {e.printStackTrace();}newInstance.get(id);return newInstance;}public static void execute(String sql)throws SQLException{AbstractExecute<IEntity> execute = ExecuteFactory.getExecute();execute.execute(sql);}}


测试类

package com.hc.execute;import com.hc.pool.IDPool;import com.hc.sample.entity.UserEntity;public class TestExecute {/** * @param args */public static void main(String[] args) throws Exception{UserEntity user  = new UserEntity();Long applyId = IDPool.getInstance().applyId();user.setId(applyId);user.setName("chujiinhui");//持久化用户user.persist();//查询此用户user = (UserEntity)user.get(applyId);System.out.println(user.getName());//更新此用户user.setName("hello");user = (UserEntity)user.get(applyId);System.out.println(user.getName());}}


 

运行结果如下:

 

insert into user_m(id,name) values (?,?)select * from user_m where 1=1 and id=?chujiinhuiupdate user_m set name=? where id=?select * from user_m where 1=1 and id=?hello


查看数据库也存在已添加的数据。

 



 

 

0 0