框架學習(1)——service層,dao層和service實現類進行資料庫操作
阿新 • • 發佈:2018-12-25
最近也是比較忙,也只能忙裡偷閒地抓緊時間接著學習一下技術,自從上次學習了maven之後,越來越對框架產生了興趣,下了好多的spring視屏,聽著老師的建議,最近也萌生了看別人的程式碼進行學習的想法,然後就上了知乎搜了搜優秀的java框架,發現了一個比較感興趣的,符合最近在學習的方面的專案。
不多說,開始主題
- 訪問資料庫的傳統方法
傳統訪問資料庫的方法非常面向過程,分為以下幾步
– 例項化connection
– 例項化statement
– 通過statement的引數sql語句訪問資料庫,返回資料進行處理
程式碼:
import java.sql.Statement;
import java.util.Properties;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DBAccess {
public static void main(String[] args) throws SQLException, FileNotFoundException, IOException
{
DBAccess access = new DBAccess();
access.test();
}
private void test() throws SQLException, FileNotFoundException, IOException
{
String url = "jdbc:postgresql://localhost:5432/rylynn";
Properties p = new Properties();
p.load(new FileInputStream("reg.txt"));
Connection connection = DriverManager.getConnection(url,p); //建立connection
Statement statement = connection.createStatement(); //建立satatement
statement.execute("insert into abo values((001),'hnb')"); //執行sql語句
ResultSet resultSet = statement.executeQuery("select number from abo where number < 2");
while(resultSet.next())
{
int id = resultSet.getInt(1);
// String name = resultSet.getString(1);
System.out.println("ID:" + id);
}
statement.close();
connection.close();
}
}
傳統資料庫訪問模式缺點顯而易見:
一就是各個模組間的耦合太緊,statement要依賴connection,connection還依賴於資料庫的種類。
二就是如果我改變的資料庫的種類,或者要提供不同的資料庫服務,那麼我就要提供大量的重複程式碼。
面向抽象的程式設計思想告訴我們要面向介面程式設計,這種程式設計模式的好處就是,各個模組之間分工明確,而且互不干擾,首先介紹一下各個層次之間分工。
- dao層:dao層叫資料訪問層,全稱為data access object,屬於一種比較底層,比較基礎的操作,具體到對於某個表、某個實體的增刪改查
- service層:service層叫服務層,被稱為服務,肯定是相比之下比較高層次的一層結構,相當於將幾種操作封裝起來,至於為什麼service層要使用介面來定義有以下幾點好處:
- 在java中介面是多繼承的,而類是單繼承的,如果你需要一個類實現多個service,你用介面可以實現,用類定義service就沒那麼靈活
- 要提供不同的資料庫的服務時,我們只需要面對介面用不同的類實現即可,而不用重複地定義類
- 程式設計規範問題,介面化的程式設計為的就是將實現封裝起來,然呼叫者只關心介面不關心實現,也就是“高內聚,低耦合”的思想。
- service實現類:也顧名思義,service實現類實現了service介面,進行具體的業務操作。
這裡用C0de8ug公開在github上面的專案的程式碼來說明
dao層、service層以及service實現類的結構:
專案中使用了mybatis框架進行資料庫的操作
以對於user的操作為例進行說明:
userdao:
public interface UserDao {
public List<User> findAll();
public User findById(String id);
public void update(User user);
public void add(User user);
public void delete(String id);
public User findByIdAndPassword(@Param("id") String username, @Param("password") String password);
public void updatePassword(@Param("userId") String id, @Param("password") String password);
User findByUsername(String username);}
在介面中對方法進行了定義,在UserDao.xml中給出了sql語句實現
在UserDao中,就對user這個實體的增刪補查各類基本的操作進行了宣告,並用mybatis框架進行實現。
下面給出部分UserDao.xml的程式碼
<select id="findAll" resultMap="user_map">
SELECT * FROM user WHERE user_id != 'admin'
</select>
<select id="findById" parameterType="String" resultMap="user_map">
SELECT * FROM user WHERE user_id = #{value}
</select>
<update id="update" parameterType="User">
UPDATE user SET password = #{password} ,authority = #{authority} WHERE user_id = #{userId}
</update>
<update id="updatePassword" parameterType="map">
UPDATE user SET password = #{password} WHERE user_id = #{userId}
</update>
<insert id="add" parameterType="User">
INSERT INTO user(user_id,password,salt,role_ids,locked) VALUES(#{userId},#{password},#{salt},#{roleIdsStr},#{locked})
</insert>
<select id="findByIdAndPassword" parameterType="map" resultMap="user_map">
SELECT * FROM user WHERE user_id = #{id} AND password = #{password}
</select>
下面來看看service層的程式碼
import com.giit.www.entity.User;
import com.giit.www.entity.custom.UserVo;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Set;
/**
* Created by c0de8ug on 16-2-9.
*/
public interface UserBiz {
public List<UserVo> findAll() throws InvocationTargetException, IllegalAccessException;
public User findById(String id);
public void update(User user);
public void add(User user);
public void delete(String id);
public void changePassword(String userId, String newPassword);
public User findByUsername(String username);
public Set<String> findRoles(String username);
public Set<String> findPermissions(String username);
}
顯然,service層裡面的方法相較於dao層中的方法進行了一層包裝,例如通過id查詢使用者,通過使用者名稱查詢使用者,是在基礎的操作上又增加了一層包裝的,實現的是相對高階的操作。最後將這些操作在serviceimpl類中實現,程式碼比較多,這裡還是隻給出了部分程式碼,
import com.giit.www.college.dao.StaffDao;
import com.giit.www.entity.Role;
import com.giit.www.entity.Staff;
import com.giit.www.entity.User;
import com.giit.www.entity.custom.UserVo;
import com.giit.www.system.dao.RoleDao;
import com.giit.www.system.dao.UserDao;
import com.giit.www.system.service.RoleBiz;
import com.giit.www.system.service.UserBiz;
import com.giit.www.util.PasswordHelper;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
/**
* Created by c0de8ug on 16-2-9.
*/
@Service
public class UserBizImpl implements UserBiz {
@Resource
UserDao userDao;
@Resource
RoleDao roleDao;
@Resource
StaffDao staffDao;
@Resource
private PasswordHelper passwordHelper;
@Resource(name = "roleBizImpl")
private RoleBiz roleBiz;
@Override
public List<UserVo> findAll() throws InvocationTargetException, IllegalAccessException {
List<UserVo> userVoList = new ArrayList<>();
List userList = userDao.findAll();
Iterator iterator = userList.iterator();
while (iterator.hasNext()) {
StringBuilder s = new StringBuilder();
User user = (User) iterator.next();
List<Long> roleIds = user.getRoleIds();
UserVo userVo = new UserVo();
BeanUtils.copyProperties(userVo, user);
if (roleIds != null) {
int i = 0;
int size = roleIds.size();
for (; i < size - 1; i++) {
Role role = roleDao.findOne(roleIds.get(i));
s.append(role.getDescription());
s.append(",");
}
Role role = roleDao.findOne(roleIds.get(i));
s.append(role.getDescription());
userVo.setRoleIdsStr(s.toString());
}
userVoList.add(userVo);
}
return userVoList;
}
由此看到,這樣進行分層,訪問資料庫和進行service之間的分工明確,如果我需要對service的需求修改,無需改變dao層的程式碼,只要在實現上改變即可,如果我有訪問資料庫的新需求,那我也只要在dao層的程式碼中增添即可。