Tags: Tax Service System project
Extracting BaseService
So far, we have written the development of three modules. Now that we’ve extracted BaseAction and BaseDao, let’s look at our Service interface.
- UserService
/** * created by ozc on 2017/5/23. */
public interface UserService {
/ / new
void save(User user);
/ / update
void update(User user);
// Delete by id
void delete(Serializable id);
// Find by id
User findObjectById(Serializable id);
// Find the list
List<User> findObjects(a) throws ServiceException;
// Export the user list
void exportExcel(List<User> userList, ServletOutputStream outputStream);
// Import the user list
void importExcel(File userExcel, String userExcelFileName);
/** * Query user ** by account and user ID@paramId User ID *@paramAccount User account *@returnUser list */
List<User> findAccount(String id, String account);
void saveUserAndRole(User user, String[] userRoleIds);
// Get the role of the user from the user ID
List<UserRole> findRoleById(String id);
void deleteUserRoleById(String[] userRoleIds);
List<User> findUserByAccountAndPassword(String account, String password);
}
Copy the code
- InfoService
/** * created by ozc on 2017/5/23. */
public interface InfoService {
/ / new
public void save(Info info);
/ / update
public void update(Info info);
// Delete by id
public void delete(Serializable id);
// Find by id
public Info findObjectById(Serializable id);
// Find the list
public List<Info> findObjects(a) ;
}
Copy the code
- RoleService
/** * Created by ozc on 2017/5/26. */
public interface RoleService {
/ / new
void save(Role role);
/ / update
void update(Role role);
// Delete O based on id
void delete(Serializable id);
// Find by id
Role findObjectById(Serializable id);
// Find the list
List<Role> findObjects(a) ;
}
Copy the code
We can see that there are methods of add, delete, modify and review in ** three Service interfaces, which is obviously duplicate code. ** Therefore, we need to extract them into a BaseService.
Extracting BaseService
Add the service package to the core module to extract the BaseService
package zhongfucheng.core.service;
import java.io.Serializable;
import java.util.List;
/** * Created by ozc on 2017/6/7. */
interface BaseService<T> {
/ / new
void save(T entity);
/ / update
void update(T entity);
// Delete by id
void delete(Serializable id);
// Find by id
T findObjectById(Serializable id);
// Find the list
List<T> findObjects(a);
}
Copy the code
- Extracting BaseServiceImpl
Our Sercive implements methods by calling objects in the DAO layer. Since this Service represents the entire project, BaseDao should be used
package zhongfucheng.core.service.impl;
import zhongfucheng.core.dao.BaseDao;
import zhongfucheng.core.service.BaseService;
import java.io.Serializable;
import java.util.List;
/** * Created by ozc on 2017/6/7. */
public abstract class BaseServiceImpl <T> implements BaseService <T>{
// Use BaseDao to manipulate the database
private BaseDao<T> baseDao;
@Override
public void save(T entity) {
baseDao.save(entity);
}
@Override
public void update(T entity) {
baseDao.update(entity);
}
@Override
public void delete(Serializable id) {
baseDao.delete(id);
}
@Override
public T findObjectById(Serializable id) {
return baseDao.findObjectById(id);
}
@Override
public List<T> findObjects(a) {
returnbaseDao.findObjects(); }}Copy the code
Take the Info module for example
- InfoService
InfoService inherits the BaseService interface, so there is a way to add, delete, change, and check. At the same time, determine the type of the generic T.
/** * created by ozc on 2017/5/23. */
public interface InfoService extends BaseService<Info> {}Copy the code
- InfoServiceImpl
InfoService is inherited, and there are methods to add or delete the query, but the specific operations are implemented in BaseServiceImpl. We inherit it and give the corresponding type of the generic T.
@Service
public class InfoServiceImpl extends BaseServiceImpl<Info> implements InfoService {}Copy the code
What’s the problem now?? We use the BaseDao variable in BaseServiceImpl to operate on the database. There is no BaseDao variable in BaseServiceImpl.
First, to be clear, we cannot inject BaseDao into BaseServiceImpl because BaseServiceImpl is itself an abstract class. So how do we instantiate BaseDao?
We can do this:
-
The InfoServiceImpl itself needs to inject the InfoDao to perform operations on the database.
-
Instead of using the property input, we use the set method for injection
-
At the same time as the injection, set the BaseDao method in BaseServiceImpl.
-
So when we inject, we can call BaseDao’s set method to pass the object we want to inject.
-
Finally, we have the baseDao variable in BaseServiceImpl.
-
InfoServiceImpl takes the InfoDao object and sets the InfoDao object into BaseServiceImpl.
@Service
public class InfoServiceImpl extends BaseServiceImpl<Info> implements InfoService {
private InfoDao infoDao;
@Resource
public void setInfoDao(InfoDao infoDao) {
super.setBaseDao(infoDao);
this.infoDao = infoDao; }}Copy the code
- BaseServiceImpl sets the set method for BaseDao.
// Use BaseDao to manipulate the database
private BaseDao<T> baseDao;
public void setBaseDao(BaseDao<T> baseDao) {
this.baseDao = baseDao;
}
Copy the code
Conditions of the query
Let’s implement the following functions:
The traditional way
In fact, it is also a query, but the query more than a condition. In the traditional way we can do this:
- Declare a method in BaseDao that receives SQL and a list of parameters
// Query the list by condition
List<T> findObjects(String sql, List<Object> objectList);
Copy the code
- Implement it in Base EDaoimpl
@Override
public List<T> findObjects(String sql, List<Object> objectList) {
Query query = getSession().createQuery(sql);
if(objectList ! =null) {
int i =0;
for (Object o : objectList) {
query.setParameter(i, o);
i++;
}
return query.list();
}
return query.list();
}
Copy the code
- BaseService defines it:
// Query the list by condition
List<T> findObjects(String sql, List<Object> objectList);
Copy the code
- It is called using baseDao in BaseServiceImpl
@Override
public List<T> findObjects(String sql, List<Object> objectList) {
return baseDao.findObjects(sql, objectList);
}
Copy the code
- Requests are processed in Action
We’ll stick with listUI, because it’s just that the parameters can be different.
- If the user is using a conditional query, it should have an Info object to bring in.
- If it is not a conditional query, there is no Info object
- Query [add new field in HQL statement] according to Info object setting whether to set parameters. So this method is universal.
public String listUI(a) {
// Query statement
String hql = "FROM Info i ";
List<Object> objectList = new ArrayList<>();
// Check whether the query is conditional based on whether info is null. If info is empty, all are queried.
if(info ! =null) {
if (StringUtils.isNotBlank(info.getTitle())) {
hql += "where i.title like ?";
objectList.add("%" + info.getTitle() + "%");
}
}
infoList = infoServiceImpl.findObjects(hql,objectList);
ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);
return "listUI";
}
Copy the code
To optimize the
Looking back at the code in our Action, we can see some inelegance:
Therefore, we want to optimize the above code with a utility class.
In response to the above problem, we found that handwritten concatenation of SQL is very error-prone. Then we can concatenate in the utility class, use the method to fetch on the line. The e object of the query is written dead, we want to be able to handle any query.
We can find the following patterns:
FROM Info WHERE title like ? and state = ? Order by createTime,state query (QueryHelper) : HQL: from; And it only appears once where clause: optional; But the keyword where appears once; Order by clause: Optional; But the keyword order by appears once; 2, query condition value set: occurrence time: when adding query condition,? Value of the query conditionCopy the code
- Utility class code:
package zhongfucheng.core.utils;
import java.util.ArrayList;
import java.util.List;
/** * Created by ozc on 2017/6/7. */
public class QueryHelper {
private String fromClause = "";
private String whereClause = "";
private String orderbyClause = "";
private List<Object> objectList;
public static String ORDER_BY_ASC = "asc";
public static String ORDER_BY_DESC = "desc";
// The FROM clause occurs only once
/** * build the FROM clause and set which table to query *@paramAClass Specifies the type the user wants to operate on@paramAlias alias * /
public QueryHelper(Class aClass, String alias) {
fromClause = " FROM " + aClass.getSimpleName() + "" + alias;
}
// Multiple conditions can be added to a WHERE clause, but the WHERE keyword appears only once
/** * Construct the WHERE clause *@param condition
* @param objects
* @return* /
public QueryHelper addCondition(String condition, Object... objects) {
// If there are already characters, then the WHERE keyword already exists
if (whereClause.length() > 0) {
whereClause += " AND " + condition;
} else {
whereClause += " WHERE" + condition;
}
// When adding a query condition,? Value of the query condition
if (objects == null) {
objectList = new ArrayList<>();
}
for (Object object : objects) {
objectList.add(object);
}
return this;
}
/ * * * *@paramProperty Specifies the property * to be sorted@paramOrder is in ascending or descending order@return* /
public QueryHelper orderBy(String property, String order) {
// If there are already characters, then the ORDER keyword already exists
if (orderbyClause.length() > 0) {
orderbyClause += "," + property +"" + order;
} else {
orderbyClause += " ORDER BY " + property+"" + order;
}
return this;
}
/** * Returns the HQL statement */
public String returnHQL(a) {
return fromClause + whereClause + orderbyClause;
}
/** * get the argument list *@return* /
public List<Object> getObjectList(a) {
returnobjectList; }}Copy the code
- The processing of the Action:
public String listUI(a) {
QueryHelper queryHelper = new QueryHelper(Info.class, "i");
// Check whether the query is conditional based on whether info is null. If info is empty, all are queried.
if(info ! =null) {
if (StringUtils.isNotBlank(info.getTitle())) {
queryHelper.addCondition(" i.title like ? "."%" + info.getTitle() + "%");
}
}
queryHelper.orderBy("i.createTime", QueryHelper.ORDER_BY_DESC);
infoList = infoServiceImpl.findObjects(queryHelper);
//infoList = infoServiceImpl.findObjects(hql,objectList);
ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);
return "listUI";
}
Copy the code
- Finally, add a queryHelper parameter to the DAO/Service layer.
conclusion
- Because the code for Service is too repetitive, we also extract Service. Extract into a BaseService interface
- BaseServiceImpl implements the BaseService interface, but uses the BaseDao object to call the implemented methods
- At this point, BaseServiceImpl is an abstract class and cannot be instantiated by itself. So how do you instantiate BaseDao?
- When our InfoServiceImpl inherits from BaseServiceImpl, we need to use the InfoDao itself to call the module’s business.
- It is easy to talk to the InfoDao instance in InfoServiceImpl, using autoload, set method injection, and so on. This time we use the set method for injection!
- What are the benefits of the set method? The InfoServiceImpl can inject InfoDao objects and perform other operations at the same time. For example, call the parent set method!!!!!!!
- We simply provide a setBaseDao method in BaseServiceImpl, and subclasses pass in their Dao. So our BaseDao is instantiated!
- Because of the uncertainty of our query condition, we need to concatenate the query condition string. It’s unsafe and error-prone. We encapsulate a query assistant object. Dedicated to queries.
If you find this article helpful, give the author a little encouragement