阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

使用DAO

29次阅读
没有评论

共计 2867 个字符,预计需要花费 8 分钟才能阅读完成。

在传统的多层应用程序中,通常是 Web 层调用业务层,业务层调用数据访问层。业务层负责处理各种业务逻辑,而数据访问层只负责对数据进行增删改查。因此,实现数据访问层就是用 JdbcTemplate 实现对数据库的操作。

编写数据访问层的时候,可以使用 DAO 模式。DAO 即 Data Access Object 的缩写,它没有什么神秘之处,实现起来基本如下:

public class UserDao {@Autowired
    JdbcTemplate jdbcTemplate;

    User getById(long id) {...}

    List<User> getUsers(int page) {...}

    User createUser(User user) {...}

    User updateUser(User user) {...}

    void deleteUser(User user) {...}
}

Spring 提供了一个 JdbcDaoSupport 类,用于简化 DAO 的实现。这个 JdbcDaoSupport 没什么复杂的,核心代码就是持有一个JdbcTemplate

public abstract class JdbcDaoSupport extends DaoSupport {private JdbcTemplate jdbcTemplate;

    public final void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;
        initTemplateConfig();}

    public final JdbcTemplate getJdbcTemplate() {return this.jdbcTemplate;
    }

    ...
}

它的意图是子类直接从 JdbcDaoSupport 继承后,可以随时调用 getJdbcTemplate() 获得 JdbcTemplate 的实例。那么问题来了:因为 JdbcDaoSupportjdbcTemplate字段没有标记@Autowired,所以,子类想要注入JdbcTemplate,还得自己想个办法:

@Component
@Transactional
public class UserDao extends JdbcDaoSupport {@Autowired
    JdbcTemplate jdbcTemplate;

    @PostConstruct
    public void init() {super.setJdbcTemplate(jdbcTemplate);
    }
}

有的童鞋可能看出来了:既然 UserDao 都已经注入了 JdbcTemplate,那再把它放到父类里,通过getJdbcTemplate() 访问岂不是多此一举?

如果使用传统的 XML 配置,并不需要编写@Autowired JdbcTemplate jdbcTemplate,但是考虑到现在基本上是使用注解的方式,我们可以编写一个AbstractDao,专门负责注入JdbcTemplate

public abstract class AbstractDao extends JdbcDaoSupport {@Autowired
    private JdbcTemplate jdbcTemplate;

    @PostConstruct
    public void init() {super.setJdbcTemplate(jdbcTemplate);
    }
}

这样,子类的代码就非常干净,可以直接调用getJdbcTemplate()

@Component
@Transactional
public class UserDao extends AbstractDao {public User getById(long id) {return getJdbcTemplate().queryForObject("SELECT * FROM users WHERE id = ?",
                new BeanPropertyRowMapper<>(User.class),
                id
        );
    }
    ...
}

倘若肯再多写一点样板代码,就可以把 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,根据实际情况决定,因为很多时候,直接在 Service 层操作数据库也是完全没有问题的。

练习

使用 DAO 模式访问数据库。

下载练习

小结

Spring 提供了 JdbcDaoSupport 来便于我们实现 DAO 模式;

可以基于泛型实现更通用、更简洁的 DAO 模式。

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-08-05发表,共计2867字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中