• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
isuning
博客园    首页    新随笔    联系   管理    订阅  订阅
Spring系列之DAO-17

DAO

Spring 中的数据访问对象 (DAO) 支持旨在以一致的方式轻松使用数据访问技术(例如 JDBC、Hibernate 或 JPA)。这使您可以相当轻松地在上述持久性技术之间切换,并且还可以让您编写代码而不必担心捕获每种技术特定的异常。

保证您的数据访问对象 (DAO) 或存储库提供异常转换的最佳方法是使用@Repository注释。此注释还允许组件扫描支持查找和配置您的 DAO 和存储库,而无需为它们提供 XML 配置条目。

任何 DAO 或存储库实现都需要访问持久性资源,具体取决于所使用的持久性技术。例如,基于 JDBC 的存储库需要访问 JDBC DataSource,而基于 JPA 的存储库需要访问 EntityManager. 完成此操作的最简单方法是使用 、 或 注释之一注入此资源@Autowired依赖@Inject项 。以下示例适用于 JPA 存储库:@Resource``@PersistenceContext

@Repository
public class JpaMovieFinder implements MovieFinder {

    @PersistenceContext
    private EntityManager entityManager;

    // ...
}

如果您使用经典的 Hibernate API,则可以注入SessionFactory,如以下示例所示:

@Repository
public class HibernateMovieFinder implements MovieFinder {

    private SessionFactory sessionFactory;

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    // ...
}

我们在这里展示的最后一个示例是针对典型的 JDBC 支持。您可以将 DataSource注入注入到初始化方法或构造函数中,您可以在其中 使用 this创建一个JdbcTemplate和其他数据访问支持类(例如和其他) 。以下示例自动装配 a :SimpleJdbcCall``DataSource``DataSource

@Repository
public class JdbcMovieFinder implements MovieFinder {

    private JdbcTemplate jdbcTemplate;

    @Autowired
    public void init(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    // ...
}

简化实例

倘若肯再多写一点样板代码,就可以把AbstractDao改成泛型,并实现getById(),getAll(),deleteById()这样的通用方法:

public abstract class AbstractDao<T> extends JdbcDaoSupport {
    private String table;
    private Class<T> entityClass;
    private RowMapper<T> rowMapper;

    public AbstractDao() {
        // 获取当前类型的泛型类型:
        this.entityClass = getParameterizedType();
        this.table = this.entityClass.getSimpleName().toLowerCase() + "s";
        this.rowMapper = new BeanPropertyRowMapper<>(entityClass);
    }

    public T getById(long id) {
        return getJdbcTemplate().queryForObject("SELECT * FROM " + table + " WHERE id = ?", this.rowMapper, id);
    }

    public List<T> getAll(int pageIndex) {
        int limit = 100;
        int offset = limit * (pageIndex - 1);
        return getJdbcTemplate().query("SELECT * FROM " + table + " LIMIT ? OFFSET ?",
                new Object[] { limit, offset },
                this.rowMapper);
    }

    public void deleteById(long id) {
        getJdbcTemplate().update("DELETE FROM " + table + " WHERE id = ?", id);
    }
    ...
}

这样,每个子类就自动获得了这些通用方法:

@Component
@Transactional
public class UserDao extends AbstractDao<User> {
    // 已经有了:
    // User getById(long)
    // List<User> getAll(int)
    // void deleteById(long)
}

@Component
@Transactional
public class BookDao extends AbstractDao<Book> {
    // 已经有了:
    // Book getById(long)
    // List<Book> getAll(int)
    // void deleteById(long)
}

可见,DAO模式就是一个简单的数据访问模式,可以基于泛型实现更通用、更简洁的DAO模式。

posted on 2022-05-01 22:17  吕布辕门  阅读(37)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3