MVC - 添加DAO和Service层
表间的查找
在上一篇文章结束后,数据库中添加两张表,一张用于表明用户间的好友关系:

另一张用于存储各用户的登录信息:

由此添加一个DAO接口及其实现类,用于将用户的登录信息以对象存储,此pojo的属性如下:
private Integer id;
private String loginId;
private String nickName;
private String pwd;
private UserDetail userDetail; //此用户细节信息
private List<UserLogin> friendList; //此用户的好友列表
需要注意的是,UserDetail、friendList这两个属性是不能从数据库中读取到的,所以BaseDAO的执行并不会填充这些属性,它们的作用在于登陆成功后,通过DAO或Service手动获取对应Detail和List,然后使用setter方法将这些属性填充,最后将整个对象存入Session中保存
UserLogin的DAO中有四个方法,分别是:
UserLogin getUserLoginById(int id); //根据id查找用户登录信息
UserLogin getUserLoginByPwd(String loginId, String pwd); //根据账号密码查找用户登录信息,用于登录验证
List<UserLogin> getTempFriendList(UserLogin userLogin); //根据传入的UserLogin对象的id查找该对象的所有好友
void addUserLogin(UserLogin userLogin); //添加一个用户
第三个方法返回的是一个UserLogin的数组,而一般来说,查找到的结果只能是一串id值,这里就借助到BaseDAO中已经编写好的“返回对象数组”的方法,直接将查到的好友id填充到新的实例中去,最后将这一系列好友实例组成列表并返回即可。这里方法名带了一个Temp,意思就是说返回的这个数组并不是真的好友对象的列表,而只是一个临时的、仅存储了id的对象
为什么一定要返回List<UserLogin>?为什么不能只返回id?反正最后都需要通过id拿到真正的friend对象,何必多此一举?
是因为BaseDAO要么返回单个对象,要么返回对象列表,并不能返回一串数组或是其他的什么,这是对BaseDAO的妥协
BaseDAO中,负责将搜索结果装填为对象的方法是setValues,在其中是通过名称来查找传入对象的对应属性并装填的,因此,要让id被装填,必须也让查找的结果列名为id,如此一来,BaseDAO才能正确地找到属性并赋值,所以,使用以下的SQL语句来进行查找:
select friend as id from relations where uid=?
在如此搜索后,得到的结果集列名仍是friend,百度后得知需要在数据库连接url中指定useOldAliasMetadataBehavior为true(以提交表单的形式),设置后运行正常:

如此一来,就完成了UserLoginDAO及其实现类的编写
接下来,进行Service的的引入
Service接口和实现类
Service层负责将多个DAO操作整合成一整个具有原子性的、不可分割的操作,最后返回结果
计划新建一个UserLoginService接口,实现“用户登录”、“获取用户好友”的服务
用户登录的服务逻辑是:拿到输入的loginId和pwd,然后在数据库中查询,返回查询的结果。此处可以不用判断查询结果,因为Service接口仅是单纯调用DAO的通道,判断查询结果的事情要交给Controller做。在此先明确一下以后Controller做的事情:若能查到,说明用户信息输入正确,返回此用户的登录信息;若查不到,则说明用户名或密码搜索错误。
在这个过程中需要调用的DAO:根据账号密码查询登录信息
获取用户好友时,首先调用DAO中的方法获取临时好友列表,再根据这些临时对象的id属性,调用相应DAO拿到真实的好友对象列表
在这个过程中需要调用的DAO:根据传入对象查找所有好友、根据id查找所有用户登录信息
所以,得到如下Service接口:
public interface UserLoginService {
UserLogin login(String loginId, String pwd); //提交登录
List<UserLogin> getFriendList(UserLogin userLogin); //得到好友对象列表
}
在进行此服务接口的实现时,在此处我们选择直接将UserLoginDAOImpl进行实例化,在以后进行IOC控制反转的时候再为其赋null值:
public class UserLoginServiceImpl extends BaseDAO<UserLogin> implements UserLoginService {
UserLoginDAO userLoginDAO = new UserLoginDAOImpl();
@Override
public UserLogin login(String loginId, String pwd) {
return userLoginDAO.getUserLoginByPwd(loginId,pwd);
}
@Override
public List<UserLogin> getFriendList(UserLogin userLogin) {
List<UserLogin> temp = userLoginDAO.getTempFriendList(userLogin);
List<UserLogin> res = new ArrayList<UserLogin>();
for(UserLogin friend : temp) {
friend = userLoginDAO.getUserLoginById(friend.getId());
res.add(friend);
}
return res;
}
}
如此一来,Service层就编写完毕了,由于当前只有两个DAO,且UserDetailDAO的作用还不明显,因此Service的业务逻辑较为简单,我会在之后的学习中逐渐扩充DAO的数量,并完善业务逻辑
最后,进行Service层的测试:
public class ServiceTest {
public static void main(String[] args) throws SQLException {
UserLoginService u = new UserLoginServiceImpl();
UserLogin t = u.login("u03","003");
System.out.println(t + "的好友为:");
List<UserLogin> res = u.getFriendList(t);
for (UserLogin userLogin : res)
System.out.println(userLogin);
}
}
测试结果:

最后,再编写、实现UserDetailDAO的Service,其接口为:
public interface UserDetailService {
UserDetail getDetailById(int id); //根据id获取UserDetail
}
这个Service可以帮助Controller进行要装填信息的获取,如通过登陆成功后拿到的UserLogin去找其对应的UserDetail
实现类代码略

浙公网安备 33010602011771号