Spring DAO能否合并到Service层?
Can Spring DAO be merged into Service layer?
我正在使用 spring 框架和 mybatis 开发 Web 应用程序。
在大多数情况下(至少对我而言),DAO 的方法非常简短,如下所示:
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
public User getUser(String userId) {
return (User) getSqlSession().selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
}
}
所以基本上,我需要在 DAO 中为每个被转发到使用它的服务对象的查询编写一个方法(例如 getUser(String userId)
)。这对我来说似乎是不必要的冗余。
我的同事正在努力让它变得简单。他这样写CommonDao
:
@Repository
public class CommonDao {
@Autowired
private SqlSessionTemplate sqlSession;
public Object insert(String queryId, Object params) {
return sqlSession.insert(queryId, params);
}
public Object update(String queryId, Object params) {
return sqlSession.update(queryId, params);
}
public Object delete(String queryId, Object params) {
return sqlSession.delete(queryId, params);
}
public Object selectOne(String queryId) {
return sqlSession.selectOne(queryId);
}
public Object selectOne(String queryId, Object params) {
return sqlSession.selectOne(queryId, params);
}
}
所以我们可以在如下服务中使用这些方法:
@Service
public class CrudService {
...
@Autowired
private CommonDao commonDao;
...
public UserDto selectUser(Integer userId) {
...
UserDto userDto = (UserDto) commonDao.selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
...
}
}
我有点喜欢这个方法,因为它使代码更简单。但我不确定这是一个值得遵循的好习惯。
嗯,你的纠结,在 MyBatis 中是正常的。
您的同事为您指出了某个方向...但是 CommonDao
在这个形状中的真正价值是什么?对我来说这不是很有用。您仍然需要几乎相同数量的代码 - 而且您仍然需要进行大量转换。
正如@Rom Konoval 所说,MapperScannerConfigurer
可以生成映射器实现 - 这样您就不会编写冗余实现并具有类型安全的好处 - 类型转换仍然发生但被隐藏了你。你可以试试。
这是 GitHub 上的 sample usage。
或者,您可以自己创建 DAO 实现(就像您已经做的那样),或者直接在您的服务中使用 SqlSessionTemplate
。由你决定。保持您的代码库尽可能小并遵循常识。
要避免样板代码并同时具有类型安全性并使您的服务层不受 DAO 实现细节的影响,请使用 spring-mybatis MapperScannerConfigurer
。
在这种情况下,您可以用类型安全的映射器替换您的 DAO。
相当于你的 DAO
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
public User getUser(String userId) {
return (User)getSqlSession().selectOne(
"org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
}
}
将是这个映射器 class
package org.mybatis.spring.sample.mapper;
interface UserMapper {
User getUser(String userId);
}
如果将其重命名为 UserDao
,则根本不需要更改服务。服务仅依赖于声明的映射器接口。
请注意,您需要定义此接口以确保类型安全并定义服务的依赖性。
当然你需要配置 spring-mybatis
以便它根据你的代码中定义的映射器接口生成映射器实现。这相当简单,并且有 many options 如何做到这一点。
我正在使用 spring 框架和 mybatis 开发 Web 应用程序。
在大多数情况下(至少对我而言),DAO 的方法非常简短,如下所示:
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
public User getUser(String userId) {
return (User) getSqlSession().selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
}
}
所以基本上,我需要在 DAO 中为每个被转发到使用它的服务对象的查询编写一个方法(例如 getUser(String userId)
)。这对我来说似乎是不必要的冗余。
我的同事正在努力让它变得简单。他这样写CommonDao
:
@Repository
public class CommonDao {
@Autowired
private SqlSessionTemplate sqlSession;
public Object insert(String queryId, Object params) {
return sqlSession.insert(queryId, params);
}
public Object update(String queryId, Object params) {
return sqlSession.update(queryId, params);
}
public Object delete(String queryId, Object params) {
return sqlSession.delete(queryId, params);
}
public Object selectOne(String queryId) {
return sqlSession.selectOne(queryId);
}
public Object selectOne(String queryId, Object params) {
return sqlSession.selectOne(queryId, params);
}
}
所以我们可以在如下服务中使用这些方法:
@Service
public class CrudService {
...
@Autowired
private CommonDao commonDao;
...
public UserDto selectUser(Integer userId) {
...
UserDto userDto = (UserDto) commonDao.selectOne("org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
...
}
}
我有点喜欢这个方法,因为它使代码更简单。但我不确定这是一个值得遵循的好习惯。
嗯,你的纠结,在 MyBatis 中是正常的。
您的同事为您指出了某个方向...但是 CommonDao
在这个形状中的真正价值是什么?对我来说这不是很有用。您仍然需要几乎相同数量的代码 - 而且您仍然需要进行大量转换。
正如@Rom Konoval 所说,MapperScannerConfigurer
可以生成映射器实现 - 这样您就不会编写冗余实现并具有类型安全的好处 - 类型转换仍然发生但被隐藏了你。你可以试试。
这是 GitHub 上的 sample usage。
或者,您可以自己创建 DAO 实现(就像您已经做的那样),或者直接在您的服务中使用 SqlSessionTemplate
。由你决定。保持您的代码库尽可能小并遵循常识。
要避免样板代码并同时具有类型安全性并使您的服务层不受 DAO 实现细节的影响,请使用 spring-mybatis MapperScannerConfigurer
。
在这种情况下,您可以用类型安全的映射器替换您的 DAO。
相当于你的 DAO
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
public User getUser(String userId) {
return (User)getSqlSession().selectOne(
"org.mybatis.spring.sample.mapper.UserMapper.getUser", userId);
}
}
将是这个映射器 class
package org.mybatis.spring.sample.mapper;
interface UserMapper {
User getUser(String userId);
}
如果将其重命名为 UserDao
,则根本不需要更改服务。服务仅依赖于声明的映射器接口。
请注意,您需要定义此接口以确保类型安全并定义服务的依赖性。
当然你需要配置 spring-mybatis
以便它根据你的代码中定义的映射器接口生成映射器实现。这相当简单,并且有 many options 如何做到这一点。