概述
这一章节貌似有点小复杂。为了实现对象的增删改查,我们需要做点功课
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;//状态为新建
}
@Override
public void persist() throws SQLException {
//持久化对象 只有新建的对象才可以进行持久化
if(this.status == EntityStatus.NEW){
setExecute();
try{
execute.save(this);
}catch(SQLException e){
rollBack();
throw e;
}
this.status = EntityStatus.PERSIST;
}
}
@Override
public void remove() throws SQLException{
//删除用户 只有持久化的对象才可以进行删除操作
if(this.status == EntityStatus.PERSIST){
setExecute();
try {
execute.delete(this);
} catch (SQLException e) {
rollBack();
throw e;
}
this.status = EntityStatus.NEW;
}
}
@Override
public AbstractEntity get(long id) throws SQLException {
this.setId(id);
this.status = EntityStatus.QUERY;
setExecute();
execute.get(this);
this.status = EntityStatus.PERSIST;
return this;
}
@Override
public 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;
}
@Override
public void setExecute() {
execute = ExecuteFactory.getExecute();
}
@Override
public 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{
@Override
public 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{
@Override
public 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;//执行自定义sql
public 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;
}
@Override
public void commit() {
try {
conn.commit();
relase(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void rollback() {
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void relase(Connection conn) {
DBPool.getInstance().relaseConnection(conn);
}
@Override
public void execute(String sql) throws SQLException {
System.out.println(sql);
Statement stat = conn.createStatement();
stat.execute(sql);
if(autoCommit){
commit();
}
}
@Override
public 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);
}
@Override
public 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;
}
@Override
public 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;
}
@Override
public 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;
}
@Override
public 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;
}
@Override
public 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=?
chujiinhui
update user_m set name=? where id=?
select * from user_m where 1=1 and id=?
hello
查看数据库也存在已添加的数据。