Increasing efficiency has always been an eternal topic, and one of the things that can be said about efficiency in programming is to focus on doing something that separates the others from the strong ties. Here we share the common data-processing scenarios we encounter when we do crud:
• Database table fields are all designed to be non-null, even if the field can be empty on the business, the database table fields are all designed to be non-null, there are advantages and disadvantages, we think the advantages outweigh the disadvantages, so we chose it
Advantages:
1. When getting a value, you can use it directly for logical operations without determining whether the field is null or not.
The 2.mysql DBA recommends this scenario, which may be beneficial to performance, which I did not verify here.
Disadvantages:
1. The meaning of the business is not null and clear, such as the Int field default is set to 0, 0 there is no null semantic clarity.
2. When using ORM to insert data, you need to deal with non-null field values that are null.
• System field assignments, such as creator, creator ID, creation time, editor, editor ID, edit time, etc., all need to be assigned to model before actually inserting the database. These system fields are not generally associated with a specific business, only when the annotation data by what person at what time, when these non-business-related code flooded in the code, it seems a bit superfluous, and this kind of code will show redundancy, and finally bring the result is a large proportion of non-critical code.
There's no need to solve the above about default values and null semantics, because we think the benefits of having defaults are much greater than the trouble with nullable fields, so let's see how the default values and system fields are handled in general:
• All nullable fields of the model are manually assigned to the default value when operating ORM, and the int is assigned a value of 0.
• When designing a database, add a non-empty field to the default value, let the database handle the fields that are not inserted, and, if you use MyBatis, there are two insert operations mentioned in Mapper: Insert,insertselective, The latter insertselective is to deal with non-null fields, that is, the inserted model retains null values for fields that do not need to be assigned, and the SQL statements generated by the database at the time of insertion do not contain those fields, so that the default values of the database are available. If the structure of the database was originally designed without a default design, and can not change the situation is worse, the situation back to the manual assignment, there may be similar to the following code: Write a function through reflection to parse each field, if NULL to modify the default value:
public static <T> void Emptynullvalue (final T model) {
class<?> tclass = Model.getclass ();
list<field> fields = Arrays.aslist (Tclass.getdeclaredfields ());
for (Field field:fields) {
Type t = Field.gettype ();
Field.setaccessible (true);
try {
if (t = = String.class && field.get (model) = = null) {
Field.set (model, "");
} else if (t = = Bigdecimal.class && field.get (model) = = null) {
Field.set (model, new BigDecimal (0)),
Els e if (t = = Long.class && field.get (model) = = null) {
Field.set (model, new Long (0));
} else if (t = = inte Ger.class && field.get (model) = = null) {
Field.set (model, new Integer (0));
} else if (t = = Date.class &A mp;& Field.get (model) = = null) {
Field.set (model, Timehelper.localdatetimetodate ( Java.time.LocalDateTime.of (1990, 1, 1, 0, 0, 0, 0));
}
catch (Illegalaccessexception e) {
e.printstacktrace ();
}
}
Then call the function before the code calls the insert to resolve:
How to work with system fields, when you create editing data, you need to get the current user, and then update the creator information and the editor information separately, and we write a function of the reflection mechanism to handle the system fields:
Note: The following system field identification, is based on system conventions, such as creator Convention for the creation of people, according to different circumstances to do data compatibility, if the system design is good, generally in a system of all the table style should be the same.
public static <T> void Buildcreateandmodify (T model,modifymodel Modifymodel,
Boolean iscreate) {class<?> tclass = Model.getclass ();
list<field> fields = Arrays.aslist (Tclass.getdeclaredfields ()); for (Field field:fields) {Type t = field.gettype (); field.setaccessible (true); try {if (iscreate) {if (field.getname). Equals (Modifymodel.getcid ())) {Field.set (model, Modifymodel.getuserid ()),} if (Field.getname (). Equals ( Modifymodel.getcname ())) {Field.set (model, Modifymodel.getusername ()),} if (Field.getname (). Equals (
Modifymodel.getctime ())) {Field.set (model, New Date ());} if (Field.getname (). Equals (Modifymodel.getmid ())) {Field.set (model, Modifymodel.getuserid ());} if (Field.getname (). Equals (Modifymodel.getmname ())) {Field.set (model, Modifymodel.getusername ()),} if (Field.getname (). Equals ( Modifymodel.getmtime ())) {Field.set (model, New Date ());}
catch (Illegalaccessexception e) {e.printstacktrace ();}} }
Finally, in the process of data processing, according to the creation or edit to call the function to the System field assignment, such code is mixed in the business code.
Modifymodel Modifymodel = new Modifymodel ();
Modifymodel.setuserid (Getcurrentemployee (). GetId ());
Modifymodel.setusername (Getcurrentemployee (). GetName ());
if (request.getid () = = 0) {
modelhelper.buildcreateandmodify (request, Modifymodel, true);
Deptservice.insert (request);
} else {
modelhelper.buildcreateandmodify (request, Modifymodel, false);
Deptservice.updatebyprimarykey (request);
}
We can use parameter injection to solve. The idea of parameter injection is to process the received parameters further to achieve the desired effect after spring MVC receives the parameters of the foreground request. We're going to create
Managemodelconfigmethodargumentresolver, which needs to implement Handlermethodargumentresolver, this interface looks simpler and contains two core methods:
• Determine whether the parameters need to be injected, generally by judging whether there are special annotation parameters to achieve, can also add an additional parameter to judge, according to the specific business to make adjustments, I am here only if there are special comments to determine whether the need for parameter injection.
@Override Public
Boolean supportsparameter (methodparameter parameter) {
return Parameter.hasparameterannotation (Managemodelconfig.class);
}
• parameter injection, which provides an extension entry, gives us the opportunity to do further processing of the received parameters.
@Override public
Object resolveargument (methodparameter parameter, Modelandviewcontainer Mavcontainer,
Nativewebrequest webRequest, Webdatabinderfactory binderfactory) throws Exception {
Object Managemodel = Getrequestresponsebodymethodprocessor (). resolveargument (parameter, Mavcontainer, WebRequest, binderfactory);
ServletRequest ServletRequest = webrequest.getnativerequest (servletrequest.class);
Employee CurrentUser = (employee) servletrequest.getattribute (default_attribute_get_user_from_request);
if (null = = CurrentUser)
{return
managemodel;
}
Managemodelconfig parameterannotation = parameter.getparameterannotation (managemodelconfig.class);
Modelhelper.setdefaultandsystemfieldsvalue (Managemodel, Currentuser,parameterannotation.issetdefaultfieldsvalue ());
return managemodel;
}
This function has several core logics:
• Get the Parameter object, because we are dealing with the parameters of the AJAX request, the simplest injection method is to get the actual parameters through reflection to deal with the default field and the value of the system. Ajax requests are slightly different from the data bindings submitted by Form form forms, which can be referenced by the dynamic search parameter injection of the list page that was shared by the previous article (Dynamic condition search for the list page). To get the current request parameter object, we can do this with the help of the following two objects:
Requestmappinghandleradapter
Requestresponsebodymethodprocessor
Private Requestmappinghandleradapter requestmappinghandleradapter=null;
Private Requestresponsebodymethodprocessor requestresponsebodymethodprocessor = null;
Private Requestresponsebodymethodprocessor Getrequestresponsebodymethodprocessor () {
if (null== Requestmappinghandleradapter)
{
requestmappinghandleradapter=new requestmappinghandleradapter ();
}
if (null==requestresponsebodymethodprocessor) {
list
The parameter object can be taken with the following code, which is to let spring MVC parse the parameters again.
• How to get the current user, we have successfully logged in to the system, the current user's information stored in the request, and then can be in the function to obtain the current user, can also use other scenarios, such as threadlocal, caching and so on.
ServletRequest ServletRequest = webrequest.getnativerequest (Servletrequest.class);
• Call processing functions to resolve default fields and system assignments, depending on the configuration to decide whether to process the field defaults.
Managemodelconfig parameterannotation = parameter.getparameterannotation (managemodelconfig.class);
Modelhelper.setdefaultandsystemfieldsvalue (Managemodel, Currentuser,parameterannotation.issetdefaultfieldsvalue ());
Finally, we start with our parameter injection logic, where we choose to configure in XML:
<mvc:annotation-driven content-negotiation-manager= "Contentnegotiationmanager" >
<MVC: argument-resolvers>
<bean class= " Cn.wanmei.party.management.common.mvc.method.annotation.ManageModelConfigMethodArgumentResolver "/>
< /mvc:argument-resolvers>
Then look at the call in action: Just add the annotation @managemodelconfig before the parameter, and if you need to handle the default value, set the option to enable the default value to True, and the following implementation section does not see any business-independent code at all.
@RequestMapping (value = "/addorupdateuser")
@ResponseBody public
map<string, object> addorupdateuser ( @ManageModelConfig (issetdefaultfieldsvalue=true) Employeedto request) {
map<string, object> ret = new Hashmap<> ();
Validateutil.validateresult result= New Validateutil (). Validatemodel (request);
Boolean Iscreate=request.getid () = = 0;
try {
if (iscreate)
{
employeeservice.insert (request);
}
else
{
employeeservice.updatebyprimarykey (request);
}
Ret.put ("Data", "OK");
} catch (Exception e) {
ret.put ("Err", E.getmessage ());
}
return ret;
}
By customizing the implementation of the Handlermethodargumentresolver to capture the parameters of Ajax requests, using the reflection mechanism to dynamically assign the system fields and the fields that need to deal with the default values, to avoid manual intervention, has played a concise code, logic Clean, the problem of unified processing purposes. Note that these implementations are combined with the current system design, such as we think the ID field >0 on behalf of the update operation, is empty or equal to less than 0 on behalf of the creation, the system field is also the contract name and so on.