精华内容
下载资源
问答
  • 仓储模式

    2018-09-10 13:51:18
    仓储(Repository)模式自2004年首次作为领域驱动模型DDD设计的一部分引入,仓储本质上是提供提供数据的抽象,以便应用程序可以使用具有接口的相似的简单抽象集合。从此集合中CURD是通过一些列直接...仓储模式是一种...
        

    仓储(Repository)模式自2004年首次作为领域驱动模型DDD设计的一部分引入,仓储本质上是提供提供数据的抽象,以便应用程序可以使用具有接口的相似的简单抽象集合。从此集合中CURD是通过一些列直接的方法完成,无需处理连接、命令等问题,使用此种模式可帮助实现松耦合,并保持领域对象的持久性无知。

    • 仓储模式是为了在程序的数据访问层和业务逻辑层之间创建的一个抽象层
    • 仓储模式是一种数据访问模式,提供一种更松散耦合的数据访问方法
    • 将创建数据访问的逻辑写在单独的类中即仓储
    • 仓储负责和业务层进行持久化通信
    4933701-633c611d917b0ac4.png
    控制器和仓储协同工作

    仓储(Repository)是存在于工作单元和数据库之间单独分离出来的一层,是对数据访问的封装。其优点是

    • 业务层无需知道具体实现达到分离关注点
    • 提高对数据库访问的维护,对于仓储的改变并不改变业务的逻辑。
    展开全文
  • ef 仓储模式

    2020-06-18 17:11:36
    构建一个仓储模式。 Model 大家自己创建就行了,上个图,就不多说了(我是code first) IDAL namespace IDAL { public interface IBaseRepository<T> { /// <summary> /// 添加 /// </summary...

    构建一个仓储模式。

    Model
    大家自己创建就行了,上个图,就不多说了(我是code first)

     IDAL
    namespace IDAL
    {
        public interface IBaseRepository<T>
        {
            /// <summary>
            /// 添加
            /// </summary>
            /// <param name="entity">数据实体</param>
            /// <returns>添加后的数据实体</returns>
            T Add(T entity);
     
            /// <summary>
            /// 添加
            /// </summary>
            /// <param name="entity">数据实体</param>
            /// <returns>添加后的数据实体</returns>
            bool AddOK(T entity);
     
            /// <summary>
            /// 查询记录数
            /// </summary>
            /// <param name="predicate">条件表达式</param>
            /// <returns>记录数</returns>
            int Count(Expression<Func<T, bool>> predicate);
     
            /// <summary>
            /// 更新
            /// </summary>
            /// <param name="entity">数据实体</param>
            /// <returns>是否成功</returns>
            T Update(T entity);
     
            /// <summary>
            /// 更新
            /// </summary>
            /// <param name="entity">数据实体</param>
            /// <returns>是否成功</returns>
            bool UpdateOK(T entity);
     
            /// <summary>
            /// 删除
            /// </summary>
            /// <param name="entity">数据实体</param>
            /// <returns>是否成功</returns>
            bool Delete(T entity);
     
            /// <summary>
            /// 是否存在
            /// </summary>
            /// <param name="anyLambda">查询表达式</param>
            /// <returns>布尔值</returns>
            bool Exist(Expression<Func<T, bool>> anyLambda);
     
            /// <summary>
            /// 查询数据
            /// </summary>
            /// <param name="whereLambda">查询表达式</param>
            /// <returns>实体</returns>
            T Find(Expression<Func<T, bool>> whereLambda);
     
            /// <summary>
            /// 查找数据列表
            /// </summary>
            /// <typeparam name="S">排序</typeparam>
            /// <param name="whereLamdba">查询表达式</param>
            /// <returns></returns>
            IQueryable<T> FindList(Expression<Func<T, bool>> whereLamdba);
     
            /// <summary>
            /// 查找数据列表
            /// </summary>
            /// <typeparam name="S">排序</typeparam>
            /// <param name="whereLamdba">查询表达式</param>
            /// <param name="isAsc">是否升序</param>
            /// <param name="orderLamdba">排序表达式</param>
            /// <returns></returns>
            IQueryable<T> FindList<S>(Expression<Func<T, bool>> whereLamdba, bool isAsc, Expression<Func<T, S>> orderLamdba);
     
            /// <summary>
            /// 查找分页数据列表
            /// </summary>
            /// <typeparam name="S">排序</typeparam>
            /// <param name="pageIndex">当前页</param>
            /// <param name="pageSize">每页记录数</param>
            /// <param name="totalRecord">总记录数</param>
            /// <param name="whereLamdba">查询表达式</param>
            /// <param name="isAsc">是否升序</param>
            /// <param name="orderLamdba">排序表达式</param>
            /// <returns></returns>
            IQueryable<T> FindPageList<S>(int pageIndex, int pageSize, out int totalRecord, Expression<Func<T, bool>> whereLamdba, bool isAsc, Expression<Func<T, S>> orderLamdba);
     
            List<T> FindListBySQL<T>(string sql, params object[] parameters);
     
            int ExecuteBySQL(string sql, params object[] parameters);
        }
    }

    IBLL
    这里我就偷懒了(直接拷贝了idal),业务层实际可以根据自己需求封装
    namespace IBLL
    {
        public interface IBaseRepositoryBLL<T>  where T:class
        {
            /// <summary>
            /// 添加
            /// </summary>
            /// <param name="entity">数据实体</param>
            /// <returns>添加后的数据实体</returns>
            T Add(T entity);
     
            /// <summary>
            /// 添加
            /// </summary>
            /// <param name="entity">数据实体</param>
            /// <returns>添加后的数据实体</returns>
            bool AddOK(T entity);
     
            /// <summary>
            /// 查询记录数
            /// </summary>
            /// <param name="predicate">条件表达式</param>
            /// <returns>记录数</returns>
            int Count(Expression<Func<T, bool>> predicate);
     
            /// <summary>
            /// 更新
            /// </summary>
            /// <param name="entity">数据实体</param>
            /// <returns>是否成功</returns>
            T Update(T entity);
     
            /// <summary>
            /// 更新
            /// </summary>
            /// <param name="entity">数据实体</param>
            /// <returns>是否成功</returns>
            bool UpdateOK(T entity);
     
            /// <summary>
            /// 删除
            /// </summary>
            /// <param name="entity">数据实体</param>
            /// <returns>是否成功</returns>
            bool Delete(T entity);
     
            /// <summary>
            /// 是否存在
            /// </summary>
            /// <param name="anyLambda">查询表达式</param>
            /// <returns>布尔值</returns>
            bool Exist(Expression<Func<T, bool>> anyLambda);
     
            /// <summary>
            /// 查询数据
            /// </summary>
            /// <param name="whereLambda">查询表达式</param>
            /// <returns>实体</returns>
            T Find(Expression<Func<T, bool>> whereLambda);
     
            /// <summary>
            /// 查找数据列表
            /// </summary>
            /// <typeparam name="S">排序</typeparam>
            /// <param name="whereLamdba">查询表达式</param>
            /// <returns></returns>
            IQueryable<T> FindList(Expression<Func<T, bool>> whereLamdba);
     
            /// <summary>
            /// 查找数据列表
            /// </summary>
            /// <typeparam name="S">排序</typeparam>
            /// <param name="whereLamdba">查询表达式</param>
            /// <param name="isAsc">是否升序</param>
            /// <param name="orderLamdba">排序表达式</param>
            /// <returns></returns>
            IQueryable<T> FindList<S>(Expression<Func<T, bool>> whereLamdba, bool isAsc, Expression<Func<T, S>> orderLamdba);
     
            /// <summary>
            /// 查找分页数据列表
            /// </summary>
            /// <typeparam name="S">排序</typeparam>
            /// <param name="pageIndex">当前页</param>
            /// <param name="pageSize">每页记录数</param>
            /// <param name="totalRecord">总记录数</param>
            /// <param name="whereLamdba">查询表达式</param>
            /// <param name="isAsc">是否升序</param>
            /// <param name="orderLamdba">排序表达式</param>
            /// <returns></returns>
            IQueryable<T> FindPageList<S>(int pageIndex, int pageSize, out int totalRecord, Expression<Func<T, bool>> whereLamdba, bool isAsc, Expression<Func<T, S>> orderLamdba);
     
            List<T> FindListBySQL<T>(string sql, params object[] parameters);
            int ExecuteBySQL(string sql, params object[] parameters);
        }


    以上工作做完后,我们开始准备  DAL和 BLL了。

    分别创建DAL和 BLL类库。(你要是文件夹,也无所谓)

    DAL
    先来一个图形象一点
    (截图中,大家可能看到了BaseRespositoryRedis.cs 顾名思义,不解释了。下一章我贴代码吧。其实也没什么好说的)

    ELDBEntity.cs(其实就是我们的 DBContext,不多说了吧)

    namespace DAL.DBContext
    {
        public class ELDBEntity : DbContext
        {
            public ELDBEntity()
                : base("name=Entities")
            {
            }
        
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                
                
            }
           
            public DbSet<SYS_User> SYS_User { get; set; }
            public DbSet<SYS_UserAccess> SYS_UserAccess { get; set; }
            
        }
    }

    DbContextFactory
    这个文件,稍微介绍一下,

    主要是为了让每一个用户,从始至终只使用自己的dbcontext。

    简单点说,每个用户都会有属于自己的dbcontext。但是只会有一个,不会有多个。

    代码:

    namespace DAL
    {
        public class DbContextFactory
        {
            public static ELDBEntity GetCurrentContext()
            {
                ELDBEntity _nContext = CallContext.GetData("ELDBEntity") as ELDBEntity;
                if (_nContext == null)
                {
                    _nContext = new ELDBEntity();
                    CallContext.SetData("ELDBEntity", _nContext);
                }
                
                return _nContext;
            }
        }
    }

    BaseRepository.cs:
    由于我封装了 分页方法,所有添加了Webdiyer.WebControls.Mvc引用,

    大家可以通过nuget 查找MvcPager 添加这个dll

    不喜欢的童鞋,自行删除。

    另外,我封装了通过sql语句来增删改查。

    using Webdiyer.WebControls.Mvc;
    namespace DAL.Base
    {
        public class BaseRepository<T> :BaseClass, IBaseRepository<T> where T: class
        {
            public ELDBEntity dbEF = DbContextFactory.GetCurrentContext();
            //public ELDBEntity dbEF = ELDBEntity();
            
            public virtual T Add(T entity)
            {
                dbEF.Entry<T>(entity).State = EntityState.Added;
                dbEF.SaveChanges();
                return entity;
            }
     
            public virtual bool AddOK(T entity)
            {
                dbEF.Entry<T>(entity).State = EntityState.Added;
                return dbEF.SaveChanges() > 0;            
            }
     
            public virtual int Count(Expression<Func<T, bool>> predicate)
            {
                return dbEF.Set<T>().AsNoTracking().Count(predicate);
            }
     
            public virtual T Update(T entity)
            {
                dbEF.Set<T>().Attach(entity);
                dbEF.Entry<T>(entity).State = EntityState.Modified;
                dbEF.SaveChanges();
                return entity;
            }
     
            public virtual bool UpdateOK(T entity)
            {
                dbEF.Set<T>().Attach(entity);
                dbEF.Entry<T>(entity).State = EntityState.Modified;
                return dbEF.SaveChanges() > 0;
            }
     
            public virtual bool Delete(T entity)
            {
                dbEF.Set<T>().Attach(entity);
                dbEF.Entry<T>(entity).State = EntityState.Deleted;
               
                return dbEF.SaveChanges() > 0;
            }
     
            public virtual bool Exist(Expression<Func<T, bool>> anyLambda)
            {
                return dbEF.Set<T>().AsNoTracking().Any(anyLambda);
            }
     
            public virtual T Find(Expression<Func<T, bool>> whereLambda)
            {
                T _entity = dbEF.Set<T>().AsNoTracking().FirstOrDefault<T>(whereLambda);
                return _entity;
            }
     
            public virtual IQueryable<T> FindList(Expression<Func<T, bool>> whereLamdba)
            {
                var _list = dbEF.Set<T>().AsNoTracking().Where<T>(whereLamdba);
                return _list;
            }
     
            public virtual IQueryable<T> FindList<S>(Expression<Func<T, bool>> whereLamdba, bool isAsc, Expression<Func<T, S>> orderLamdba)
            {
                var _list = dbEF.Set<T>().AsNoTracking().Where<T>(whereLamdba);
                if (isAsc) _list = _list.OrderBy<T, S>(orderLamdba);
                else _list = _list.OrderByDescending<T, S>(orderLamdba);
                return _list;
            }
     
            public virtual IQueryable<T> FindPageList<S>(int pageIndex, int pageSize, out int totalRecord, Expression<Func<T, bool>> whereLamdba, bool isAsc, Expression<Func<T, S>> orderLamdba)
            {
                var _list = dbEF.Set<T>().AsNoTracking().Where<T>(whereLamdba);
                totalRecord = _list.Count();
                if (isAsc) _list = _list.OrderBy<T, S>(orderLamdba).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);
                else _list = _list.OrderByDescending<T, S>(orderLamdba).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);
                return _list;
            }
            public virtual PagedList<T> FindPageList1<S>(int pageIndex, int pageSize, out int totalRecord, Expression<Func<T, bool>> whereLamdba, bool isAsc, Expression<Func<T, S>> orderLamdba)
            {
                var _list = dbEF.Set<T>().AsNoTracking().Where<T>(whereLamdba);
                totalRecord = _list.Count();
                PagedList<T> resultList = null;
                if (isAsc) resultList = _list.OrderBy<T, S>(orderLamdba).ToPagedList(pageIndex,pageSize);
                else resultList = _list.OrderByDescending<T, S>(orderLamdba).ToPagedList(pageIndex, pageSize);
                return resultList;
            }
     
     
            public virtual List<T> FindListBySQL<T>(string sql, params object[] parameters)
            {
                var list = dbEF.Database.SqlQuery<T>(sql, parameters).ToList();
                return list;
            }
     
            public virtual int ExecuteBySQL(string sql, params object[] parameters)
            {
                var q = dbEF.Database.ExecuteSqlCommand(sql, parameters);
                return q;
            }
        }
    }

    BLL
    BaseRepositoryBLL.cs
    namespace BLL.Base
    {
        public class BaseRepositoryBLL<T> :BaseClass, IBaseRepositoryBLL<T> where T:class
        {
            BaseRepository<T> obj = new BaseRepository<T>();
            public virtual T Add(T entity)
            {
                return obj.Add(entity);
            }
     
            public virtual bool AddOK(T entity)
            {
                return obj.AddOK(entity);
            }
     
            public virtual int Count(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
            {
                return obj.Count(predicate);
            }
     
            public virtual T Update(T entity)
            {
                return obj.Update(entity);
            }
     
            public virtual bool UpdateOK(T entity)
            {
                return obj.UpdateOK(entity);
            }
     
            public virtual bool Delete(T entity)
            {
                return obj.Delete(entity);
            }
     
            public virtual bool Exist(System.Linq.Expressions.Expression<Func<T, bool>> anyLambda)
            {
                return obj.Exist(anyLambda);
            }
     
            public virtual T Find(Expression<Func<T, bool>> whereLambda)
            {
                return obj.Find(whereLambda);
            }
     
            public virtual IQueryable<T> FindList(Expression<Func<T, bool>> whereLamdba)
            {
                var _list = obj.FindList(whereLamdba);
                return _list;
            }
     
            public virtual IQueryable<T> FindList<S>(Expression<Func<T, bool>> whereLamdba, bool isAsc, System.Linq.Expressions.Expression<Func<T, S>> orderLamdba)
            {
                return obj.FindList<S>(whereLamdba, isAsc, orderLamdba);
            }
     
            public virtual IQueryable<T> FindPageList<S>(int pageIndex, int pageSize, out int totalRecord, Expression<Func<T, bool>> whereLamdba, bool isAsc, Expression<Func<T, S>> orderLamdba)
            {
                return obj.FindPageList<S>(pageIndex, pageSize, out totalRecord, whereLamdba, isAsc, orderLamdba);
            }
     
            public virtual PagedList<T> FindPageList1<S>(int pageIndex, int pageSize, out int totalRecord, Expression<Func<T, bool>> whereLamdba, bool isAsc, Expression<Func<T, S>> orderLamdba)
            {
                return obj.FindPageList1<S>(pageIndex, pageSize, out totalRecord, whereLamdba, isAsc, orderLamdba);
            }
     
            public virtual List<T> FindListBySQL<T>(string sql, params object[] parameters)
            {
                return obj.FindListBySQL<T>(sql, parameters);
            }
     
            public virtual int ExecuteBySQL(string sql, params object[] parameters)
            {
                return obj.ExecuteBySQL(sql, parameters);
            }
        }
    }


    调用方式
    DAL层:先创建属于某个实体对象的DAL
    namespace DAL
    {
        public class SYS_UserDAL : BaseRepository<SYS_User>
        {
            /// <summary>
            /// 登录
            /// </summary>
            /// <param name="e"></param>
            /// <returns></returns>
            //public SYS_User Login(SYS_User u)
            //{
            //    //u.Password = EncryptionClass.MD5_16(e.pwd);
            //    var q = dbEF.SYS_User.FirstOrDefault(x => x.Password == u.Password && x.Account == u.Account);
            //    return q;
     
            //}
        }
    }

    BLL层:然后创建对应的BLL
    namespace BLL
    {
        public class SYS_UserBLL : BaseRepositoryBLL<SYS_User>
        {
            SYS_UserDAL dal = new SYS_UserDAL();
            /// <summary>
            /// 添加账号
            /// </summary>
            /// <param name="entity"></param>
            /// <returns></returns>
            public bool AddUser(SYS_User entity)
            {
                return dal.AddOK(entity);
            }
     
        }
    }
     

    展开全文
  • Java 仓储模式

    2019-06-21 15:58:50
    使用的Spring boot +Jpa ...下面就是设计的仓储模式 先看下SysUser: @MappedSuperclass public class SuperBaseModel { //基本属性 } @MappedSuperclass public class BaseModel extends Su...

    使用的Spring boot +Jpa

    项目层级:

    common里包含了model,以及一些viewModel等等

    下面就是设计的仓储模式

    先看下SysUser:

    @MappedSuperclass
    public class SuperBaseModel {
    //基本属性
    }
    @MappedSuperclass
    public class BaseModel extends SuperBaseModel {
    //枚举值:https://blog.csdn.net/hanjun0612/article/details/72845960
        private Integer isValid =EnumList.ValidEnum.Valid.getEnumItem().getItemKey();
    
        @Column(name="IsValid")
        public Integer getIsValid() {
            return isValid;
        }
    
        public void setIsValid(Integer isValid) {
            this.isValid = isValid;
        }
        
      
    }
    @Entity
    @Table(name = "sys_user", catalog = "kps_business")
    @DynamicUpdate
    public class SysUser extends BaseModel implements java.io.Serializable {
      //get set  
    }

    枚举值,请查看  https://blog.csdn.net/hanjun0612/article/details/72845960

     

    一,dao创建MyJpa

    @NoRepositoryBean
    public interface MyJpaRepository<T,ID extends Serializable> extends JpaRepository <T,ID>,JpaSpecificationExecutor<T>{
    
    }

    接着创建一个 SysUserDao,里面额外创建了3个方法。

    @Repository
    public interface SysUserDao extends MyJpaRepository<SysUser, String>{
        public SysUser getByAccount(String account);
        public SysUser getByAccountAndPlatformUUID(String account,String platformUUID);
        public SysUser getByUserUUId(String userUUId);
    }

    这里MyJpaRepository<SysUser,String>

    首先传入的是对象SysUser,其次传入了一个String 的UUID

    如果你是Integer,那你自行修改就可以了。

     

    二,service

    先创建BaseSuperService

    public interface BaseSuperService<T extends SuperBaseModel,ID extends Serializable> extends MyJpaRepository<T, ID> {
    	/**
    	 * 分页查询
    	 */
    	PageResult<T> pagedList(T entity,Integer currentPage,Integer pageSize,Order...orders);
    	
    	PageResult<T> pagedList(T entity,Integer currentPage,Order...orders);
    }

    接着创建BaseService

    public interface BaseService<T extends BaseModel,ID extends Serializable> extends BaseSuperService<T, ID> {
    
    	/**
    	 * 分页查询(有效的记录)
    	 */
    	PageResult<T> pagedListForVaild(T entity,Integer currentPage,Integer pageSize,Order...orders) throws Exception;
    	
    	PageResult<T> pagedListForVaild(T entity,Integer currentPage,Order...orders) throws Exception;
    
    }

    这里,你可以只创建一个BaseService。我是由于后期有两个领域模型

    第一个领域模型,只需要BaseSuperService的pagedList方法

    第二个领域模型,需要BaseSuperService的pagedList方法,以及BaseService的PagedListForVaild方法

    因此才创建了两个层级。

     

    最后创建UserService

    public interface SysUserService extends BaseService<SysUser,String>{
        public SysUser getByAccountAndPlatformUUID(String account,String platformUUID);
        public SysUser getByAccount(String account);
        public SysUser getByUserUUId(String userUUID);
    }

     

    三,创建Impl

    首先创建BaseSuperServiceImpl

    @SuppressWarnings({"unchecked", "rawtypes"})
    public class BaseSuperServiceImpl< K extends MyJpaRepository<T,ID>, T extends SuperBaseModel,ID extends Serializable> implements BaseSuperService<T,ID> {
    	protected Class<T> clazz;
    	protected String keyName; //主键属性名
    	protected Method getMethod; //得到主键对应的get方法
    	protected String sortName="createTime"; //默认字段排序  由于个别表key为UUID,不能按key排序
    	@Value("${isDebug}")
    	protected boolean isDebug;
    	@Autowired
    	protected K dao;
    	@Autowired
    	protected StringRedisTemplate redisTemplate;
    	@PersistenceContext
    	protected EntityManager em;// 类似hibernate session
    
    	public BaseSuperServiceImpl() {
    		ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
    		clazz = (Class<T>) type.getActualTypeArguments()[1];
    		getMethod = HibernateUtil.getKeyMethod(clazz);
    		String idname =getMethod.getName().substring(3);
    		idname = idname.substring(0, 1).toLowerCase() + idname.substring(1);
    		keyName = idname; //得到主键id名
    	}
    
    	@Override
    	public List<T> findAll() {
    		return dao.findAll();
    	}
    
    	@Override
    	public List<T> findAll(Sort sort) {
    		return dao.findAll(sort);
    	}
    
    	@Override
    	public Page<T> findAll(Pageable pageable) {
    		return dao.findAll(pageable);
    	}
    
    	@Override
    	public List<T> findAll(Iterable<ID> integers) {
    		return dao.findAll(integers);
    	}
    
    	@Override
    	public long count() {
    		return dao.count();
    	}
    
    	@Override
    	public void delete(ID id) {
               dao.delete(id);
    	}
    
    	@Override
    	public void delete(T entity) {
    		dao.delete(entity);
    	}
    
    	@Override
    	public void delete(Iterable<? extends T> entities) {
    		dao.delete(entities);
    	}
    
    	@Override
    	public void deleteAll() {
    		dao.deleteAll();
    	}
    
    	@Override
    	public <S extends T> S save(S entity) {
    		try {
    			SysUser curUser = WebUtil.getCurrentUser(isDebug);
    			ID id = (ID) getMethod.invoke(entity);
    			//如果新增,reateTime,createUserUUID没给值,统一赋值
                if(id==null){
                	if(entity.getCreateTime()==null) entity.setCreateTime(DateUtil.getCurDate());
                	if(entity.getCreateUserUUID()==null) entity.setCreateUserUUID(curUser.getUserUUId());
                }
    			return dao.save(entity);
    		} catch (Exception e) {
    			LogerHelper.error(e);
    		}
    		return null;
    	}
    
    	@Override
    	public <S extends T> List<S> save(Iterable<S> entities) {
    		return dao.save(entities);
    	}
    
    	@Override
    	public T findOne(ID id) {
    		return dao.findOne(id);
    	}
    
    	@Override
    	public boolean exists(ID id) {
    		return dao.exists(id);
    	}
    
    	@Override
    	public void flush() {
           dao.flush();
    	}
    
    	@Override
    	public <S extends T> S saveAndFlush(S entity) {
    		return dao.saveAndFlush(entity);
    	}
    
    	@Override
    	public void deleteInBatch(Iterable<T> entities) {
    		dao.deleteInBatch(entities);
    	}
    
    	@Override
    	public void deleteAllInBatch() {
           dao.deleteAllInBatch();
    	}
    
    	@Override
    	public T getOne(ID id) {
    		return dao.getOne(id);
    	}
    
    	@Override
    	public <S extends T> S findOne(Example<S> example) {
    		return dao.findOne(example);
    	}
    
    	@Override
    	public <S extends T> List<S> findAll(Example<S> example) {
    		return dao.findAll(example);
    	}
    
    	@Override
    	public <S extends T> List<S> findAll(Example<S> example, Sort sort) {
    		return dao.findAll(example,sort);
    	}
    
    	@Override
    	public <S extends T> Page<S> findAll(Example<S> example, Pageable pageable) {
    		return dao.findAll(example, pageable);
    	}
    
    	@Override
    	public <S extends T> long count(Example<S> example) {
    		return dao.count(example);
    	}
    
    	@Override
    	public <S extends T> boolean exists(Example<S> example) {
    		return dao.exists(example);
    	}
    
    	@Override
    	public PageResult<T> pagedList(T entity, Integer currentPage, Integer pageSize, Order... orders) {
    		Sort s = null;
    		if (orders != null && orders.length > 0) {
    			s = new Sort(orders);
    		} else {
    			s = new Sort(new Order(Direction.DESC, sortName));
    		}
    		PageRequest pr = new PageRequest(currentPage - 1, pageSize, s);
    		
    		Page<T> p =  this.findAll(pr);
    		Integer fromItem = PageUtil.getOffset(currentPage, pageSize);
    		return new PageResult<T>(currentPage, pageSize, p.getContent(), (int)p.getTotalElements(), p.getTotalPages(), fromItem,  p.getContent().size());
    	}
    	
    	@Override
    	public PageResult<T> pagedList(T entity, Integer currentPage, Order... orders) {
             return this.pagedList(entity, currentPage,PageUtil.PAGE_SIZE,orders);	
    	}
    	
    	
    	protected List<Map> exectSqlMap(Query query) {
    		query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
    		return query.getResultList();
    	}
    	
    	protected Map exectSqlMap2(Query query) {
    		List<Map> list = exectSqlMap(query);
    		return ListUtil.notEmpty(list)?list.get(0):null;
    	}
    	
    	
    	protected PageResult<T> gerPageResult(Integer currentPage, Integer pageSize, 
    			Specification<T> sf,Order... orders) {
    		//构建分页信息
    		Sort s = null;
    		if (orders != null && orders.length > 0) {
    			s = new Sort(orders);
    		} else {
    			s = new Sort(new Order(Direction.DESC, sortName));
    		}
    		PageRequest pr = new PageRequest(currentPage - 1, pageSize, s);
    		Page<T> p = sf==null?this.findAll(pr):this.findAll(sf,pr);
    		Integer fromItem = PageUtil.getOffset(currentPage, pageSize);
    		return new PageResult<T>(currentPage, pageSize, p.getContent(), (int)p.getTotalElements(), p.getTotalPages(), fromItem, p.getContent().size());
    	}
    
    	@Override
    	public T findOne(Specification<T> spec) {
    		return dao.findOne(spec);
    	}
    
    	@Override
    	public List<T> findAll(Specification<T> spec) {
    		return dao.findAll(spec);
    	}
    
    	@Override
    	public Page<T> findAll(Specification<T> spec, Pageable pageable) {
    		return dao.findAll(spec, pageable);
    	}
    
    	@Override
    	public List<T> findAll(Specification<T> spec, Sort sort) {
    		return dao.findAll(spec, sort);
    	}
    
    	@Override
    	public long count(Specification<T> spec) {
    		return dao.count(spec);
    	}
    
    
    	
    }

    基本上,重写了所有的方法。

    然后创建:BaseServiceImpl

    public class BaseServiceImpl<K extends MyJpaRepository<T,ID>,T extends BaseModel,ID extends Serializable> extends BaseSuperServiceImpl<K,T,ID> implements BaseService<T,ID> {
    
    	@Override
    	public PageResult<T> pagedListForVaild(T entity, Integer currentPage, Integer pageSize, Order... orders) throws Exception {
    		Sort s = null;
    		if (orders != null && orders.length > 0) {
    			s = new Sort(orders);
    		} else {
    			s = new Sort(new Order(Direction.DESC, sortName));
    		}
    		PageRequest pr = new PageRequest(currentPage - 1, pageSize, s);
    		T model = clazz.newInstance();
    		model.setIsValid(EnumList.ValidEnum.Valid.getEnumItem().getItemKey());
    		Example<T> example = Example.of(model);
    		Page<T> p =  dao.findAll(example, pr);
    		Integer fromItem = PageUtil.getOffset(currentPage, pageSize);
    		return new PageResult<T>(currentPage, pageSize, p.getContent(), (int)p.getTotalElements(), p.getTotalPages(), fromItem,  p.getContent().size());
    	
    	}
    
    	@Override
    	public <S extends T> S save(S entity) {
    		//如果isValid没给值,统一赋值
    		if(entity.getIsValid()==null) entity.setIsValid(EnumList.ValidEnum.Valid.getEnumItem().getItemKey());
    		return super.save(entity);
    	}
    
    	@Override
    	public PageResult<T> pagedListForVaild(T entity, Integer currentPage, Order... orders) throws Exception {
    		return this.pagedListForVaild(entity, currentPage,PageUtil.PAGE_SIZE,orders);
    	}
    	
    }

     

    最后创建UserServiceImpl

    @Service("userService")
    public class SysUserServiceImpl extends BaseServiceImpl<SysUserDao,SysUser,String>  implements SysUserService {
    
        public SysUser getByUserUUId(String userUUId){
            return  dao.getByUserUUId(userUUId);
    
        }
    	@Override
    	public SysUser getByAccountAndPlatformUUID(String account,String platformUUID) {
    		return dao.getByAccountAndPlatformUUID(account,platformUUID);
    	}
    	@Override
    	public SysUser getByAccount(String account) {
    		return dao.getByAccount(account);
    	}
    
    	@Override
    	public PageResult<SysUser> pagedList(SysUser entity, Integer currentPage, Integer pageSize, Order... orders) {
    		if(entity==null){
    			return super.pagedList(entity, currentPage, pageSize, orders);
    		}
    		
    		//构建查询条件
    		Specification<SysUser> sf = new Specification<SysUser>(){
    			@Override
    			public Predicate toPredicate(Root<SysUser> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
    				String name = entity.getUserNameCn();
    				Integer isValid = entity.getIsValid();
    				List<Predicate> list = new ArrayList<Predicate>();
    				if (StringUtils.isNotBlank(name)) {
    					name = name.toLowerCase();
    					Predicate p1 = cb.like(cb.lower(root.get("userNameCn")), "%" + name + "%");
    					Predicate p2 = cb.like(cb.lower(root.get("userNameEn")), "%" + name + "%");
    					Predicate p3 = cb.like(cb.lower(root.get("account")), "%" + name+ "%");
    				    list.add(cb.or(p1,p2,p3));
    				}
    				if(isValid!=null){
    					list.add(cb.equal(root.get("isValid"),isValid));
    				}
    				Predicate[] p = new Predicate[list.size()];
    	            return cb.and(list.toArray(p));
    			}
    		};
    		
    		return super.gerPageResult(currentPage, pageSize,sf,orders);
    	
    	}
    	
    	
    	
    }

    这里,我额外演示一下重写了PagedList方法。

     

    四,测试调用

    @RunWith(value=SpringRunner.class)
    @SpringBootTest(classes={WebAPISYSApp.class})
    public class SysUserTest{
    	@Autowired
    	private SysUserService userService;
    
        @Test
    	public void findUser(){
    		SysUser user = userService.findOne("0c867aca-d1eb-11e8-9aa5-0022198292f8");
    		logger.info(user.getAccount());
    		
    	}
    	
    }

     

    展开全文
  • 【导读】仓储模式我们已耳熟能详,但当我们将其进行应用时,真的是那么得心应手吗?确定是解放了生产力吗?这到底是怎样的一个存在,确定不是反模式?一篇详文我们探讨仓储模式,这里仅我个人的思考,...
    【导读】仓储模式我们已耳熟能详,但当我们将其进行应用时,真的是那么得心应手吗?确定是解放了生产力吗?这到底是怎样的一个存在,确定不是反模式?

    一篇详文我们探讨仓储模式,这里我个人的思考,若有更深刻的理解,请在留言中给出

    仓储反模式

    5年前我在Web APi中使用EntityFramework中写了一个仓储模式,并将其放在我个人github上,此种模式也完全是参考所流行的网传模式,现如今在我看来那是极其错误的仓储模式形式,当时在EntityFramework中有IDbSet接口,然后我们又定义一个IDbContext接口等等,大同小异,接下来我们看看在.NET Core中大多是如何使用的呢?

    ???? 定义通用IRepository接口

    public interface IRepository<TEntity> where TEntity : class
    {
        /// <summary>
        /// 通过id获得实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        TEntity GetById(object id);
        
        //其他诸如修改、删除、查询接口
    }
    

    当然还有泛型类可能需要基础子基础类等等,这里我们一并忽略

    ???? 定义EntityRepository实现IRepository接口

    public abstract class EntityRepository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        private readonly DbContext _context;
    
        public EntityRepository(DbContext context)
        {
            _context = context;
        }
    
        /// <summary>
        /// 通过id获取实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public TEntity GetById(object id)
        {
            return _context.Set<TEntity>().Find(id);
        }
    }

    ???? 定义业务仓储接口IUserRepository接口

    public interface IUserRepository : IRepository<User>
    {
        /// <summary>
        /// 其他非通用接口
        /// </summary>
        /// <returns></returns>
        List<User> Other();
    }
    

    ???? 定义业务仓储接口具体实现UserRepository

    public class UserRepository : EntityRepository<User>, IUserRepository
    {
        public List<User> Other()
        {
            throw new NotImplementedException();
        }
    }
    

    我们定义基础通用接口和实现,然后每一个业务都定义一个仓储接口和实现,最后将其进行注入,如下:

      services.AddDbContext<EFCoreDbContext>(options =>
      {
          options.UseSqlServer(@"Server=.;Database=EFCore;Trusted_Connection=True;");
      });
    
      services.AddScoped(typeof(IRepository<>), typeof(EntityRepository<>));
      
      services.AddScoped<IUserRepository, UserRepository>();
      
      services.AddScoped<IUserService, UserService>());

    有一部分童鞋在项目中可能就是使用如上方式,每一个具体仓储实现我们将其看成传统的数据访问层,紧接着我们还定义一套业务层即服务层,如此第一眼看来和传统三层架构无任何区别,只是分层名称有所不同而已

    每一个具体仓储接口都继承基础仓储接口,然后每个具体仓储实现继承基础仓储实现,对于服务层同理,反观上述一系列操作本质,其实我们回到了原点,那还不如直接通过上下文操作一步到位来的爽快

    上述仓储模式并没有带来任何益处,分层明确性从而加大了复杂性和重复性,根本没有解放生产率,我们将专注力全部放在了定义多层接口和实现上而不是业务逻辑,如此使用,这就是仓储模式的反模式实现

    仓储模式思考

    所有脱离实际项目和业务的思考都是耍流氓,若只是小型项目,直接通过上下文操作未尝不可,既然用到了仓储模式说明是想从一定程度上解决项目中所遇到的痛点所在,要不然只是随波逐流,终将是自我打脸

    根据如下官方在微服务所使用仓储链接,官方推崇仓储模式,但在其链接中是直接在具体仓储实现中所使用上下文进行操作,毫无以为这没半点毛病

    EntityFramework Core基础设施持久化层

    https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-implementation-entity-framework-core

    但我们想在上下文的基础上进一步将基本增、删、改、查询进行封装,那么我们如何封装基础仓储而避免出现反模式呢?

    我思仓储模式

    在进行改造之前,我们思考两个潜在需要解决的重点问题

    其一,每一个具体业务仓储实现,定义仓储接口是一定必要的吗?我认为完全没必要,有的童鞋就疑惑了,若我们有非封装基础通用接口,需额外定义,那怎么搞,我们可以基于基础仓储接口定义扩展方法

    其二,若与其他仓储进行互操作,此时基础仓储不满足需求,那怎么搞,我们可以在基础仓储接口中定义暴露获取上下文Set属性

    其三,若非常复杂的查询,可通过底层连接实现或引入Dapper

    首先,我们保持上述封装基础仓储接口前提下添加暴露上下文Set属性,如下:

      /// <summary>
      /// 基础通用接口
      /// </summary>
      /// <typeparam name="TEntity"></typeparam>
      public interface IRepository<T> where T : class
      {
          IQueryable<T> Queryable { get; }
          T GetById(object id);
      }

    上述我们将基础仓储接口具体实现类,将其定义为抽象,既然我们封装了针对基础仓储接口的实现,外部只需调用即可,那么该类理论上就不应该被继承,所以接下来我们将其修饰为密封类,如下:

    public sealed class EntityRepository<T> : IRepository<T> where T : class
    {
        private readonly DbContext _context;
    
        public EntityRepository(DbContext context)
        {
            _context = context;
        }
    
        public T GetById(object id)
        {
            return _context.Set<T>().Find(id);
        }
    }
    

    我们从容器中获取上下文并进一步暴露上下文Set属性

    public sealed class EntityRepository<T> : IRepository<T> where T : class
    {
        private readonly IServiceProvider _serviceProvider;
    
        private EFCoreDbContext _context => (EFCoreDbContext)
            _serviceProvider.GetService(typeof(EFCoreDbContext));
    
        private DbSet<T> Set => _context.Set<T>();
    
        public IQueryable<T> Queryable => Set;
    
        public EntityRepository(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }
    
        public T GetById(object id)
        {
            return Set.Find(id);
        }
    }
    

    若为基础仓储接口不满足实现,则使用具体仓储的扩展方法

    public static class UserRepository
    {
        public static List<User> Other(this IRepository<User> repository)
        {
            // 自定义其他实现
        }
    }
    

    最后到了服务层,则是我们的业务层,我们只需要使用上述基础仓储接口或扩展方法即可

    public class UserService
    {
        private readonly IRepository<User> _repository;
        public UserService(IRepository<User>  repository)
        {
            _repository = repository;
        }
    }
    

    最后在注入时,我们将省去注册每一个具体仓储实现,如下:

      services.AddDbContext<EFCoreDbContext>(options =>
      {
          options.UseSqlServer(@"Server=.;Database=EFCore;Trusted_Connection=True;");
      });
    
      services.AddScoped(typeof(IRepository<>), typeof(EntityRepository<>));
    
      services.AddScoped<UserService>();
    

    以上只是针对第一种反模式的基本改造,对于UnitOfWork同理,其本质不过是管理操作事务,并需我们手动管理上下文释放时机就好,这里就不再多讲

    我们还可以根据项目情况可进一步实现其对应规则,比如在是否需要在进行指定操作之前实现自定义扩展,比如再抽取一个上下文接口等等,ABP vNext中则是如此,ABP vNext对EF Core扩展是我看过最完美的实现方案,接下来我们来看看

    ABP vNext仓储模式

    其核心在Volo.Abp.EntityFrameworkCore包中,将其单独剥离出来除了抽象通用封装外,还有一个则是调用了EF Core底层APi,一旦EF Core版本变动,此包也需同步更新

    ABP vNext针对EF Core做了扩展,通过查看整体实现,主要通过扩展中特性实现指定属性更新,EF Core中当模型被跟踪时,直接提交则更新变化属性,若未跟踪,我们直接Update但想要更新指定属性,这种方式不可行,在ABP vNext则得到了良好的解决

    在其EF Core包中的AbpDbContext上下文中,针对属性跟踪更改做了良好的实现,如下:

      protected virtual void ChangeTracker_Tracked(object sender, EntityTrackedEventArgs e)
      {
          FillExtraPropertiesForTrackedEntities(e);
      }
    
      protected virtual void FillExtraPropertiesForTrackedEntities(EntityTrackedEventArgs e)
      {
          var entityType = e.Entry.Metadata.ClrType;
          if (entityType == null)
          {
              return;
          }
    
          if (!(e.Entry.Entity is IHasExtraProperties entity))
          {
              return;
          }
          
          .....
      }
    

    除此之外的第二大亮点则是对UnitOfWork(工作单元)的完美方案,将其封装在Volo.Abp.Uow包中,通过UnitOfWorkManager管理UnitOfWork,其事务提交不简单是像如下形式

    private IDbContextTransaction _transaction; 
    public void BeginTransaction()
    { 
        _transaction = Database.BeginTransaction();
    }
    
    public void Commit()
    {
        try
        {
            SaveChanges();
            _transaction.Commit();
        }
        finally
        {
            _transaction.Dispose();
        }        
    }
    
    public void Rollback()
    { 
        _transaction.Rollback();
        _transaction.Dispose();
    }
    

    额外的还实现了基于环境流动的事务(AmbientUnitOfWork),反正ABP vNext在EF Core这块扩展实现令人叹服,我也在持续学习中,其他就不多讲了,博客园中讲解原理的文章比比皆是

    好了,本文到此结束,倒没什么可总结的,在文中已有概括,我们下次再会

    展开全文
  • 仓储模式的作用

    2020-05-19 11:41:02
    仓储模式作为领域驱动设计(Domain-Driven Design,DDD)的一部分,在系统设计中的使用非常广泛。它主要用于解除业务逻辑层与数据访问层之间的耦合,使业务逻辑层在存储、访问数据库时无须关心数据的来源及存储方式...
  • 仓储模式的简单理解

    2018-03-07 15:07:00
    什么是仓储模式? Repository模式是一个独立的层,介于领域层(业务逻辑层)与数据映射层(数据访问层)之间,他的存在让领域层感觉不到数据访问层的存在, 它提供一个类似集合的接口提供给领域层进行领域对象的访问。...
  • 设计模式系列:仓储模式

    千次阅读 2012-10-15 16:21:32
    仓储模式的实现 仓储Repository模式已经成为最主流的模式,数据库持久化很长时间以来是一个讨论热点,目前主要问题是:主流软件并不容易有效地将需要存储的数据映射到外部存储空间如关系数据库或NoSQL数据库。 ...
  • .NET仓储模式高级用例

    2016-11-07 16:58:00
    \主要结论\\如果需要执行基本CURD之外的其他操作,此时就有必要使用仓储(Repository)。\\t为了促进测试工作并改善可靠性,应...\\\在之前发布的文章使用实体框架、Dapper和Chain的仓储模式实现策略中,我们介绍了...
  • EntityFramework+仓储模式实现的WCF分布式服务,可接任意的数据库!
  • 一、为什么使用仓储模式个人觉得仓储模式就是升级版的三层架构,里面多了接口之间的调用,就好像仓库管理员,只是负责把仓库里面的东西交给客户,也无需知道客户要做什么,反之客户也无需知道东西在哪里,怎么存放的...
  • 数据仓储模式UnitOfWorks和Repository的实现(网上看了相关内容关于UnitOfWorks和Repository的数据仓储模式的实现,也来动手搭建下。ORM使用微软自己的EF来实现建立一个项目,使用EF,我采用的是DBFirst。建立好连接,...
  • EF,MVC,Code-First使用泛型仓储模式和工作单元实现增删查改
  • 如何实现仓储模式,在我这几年的使用过程中也积累了一些具体的实施经验。根据项目的大小、可维护性、可扩展性,以及并发我们可以做以下几种设计; 1、项目小,扩展性差 public ...
  • MVC+EF 理解和实现仓储模式和工作单元模式 原文:Understanding Repository and Unit of Work Pattern and Implementing Generic Repository in ASP.NET MVC using Entity Framework 文章介绍 在这篇文章中,我们...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 810
精华内容 324
关键字:

仓储模式