If you are already using Java programming and using any popular framework like Spring and Hibernate, then you should be familiar with the use of annotations. When working with an existing framework, it is usually enough to use its annotation. But do you sometimes have to create your own need to create your own annotation?
Not long ago, I found a reason for creating an annotation, which was a project that involved common data stored in a variety of databases.
Scene description
The business has a variety of databases that store the same data, and they have their own different ways to keep data update. The business has planned to integrate all these data into one main database to reduce the involving multiple data sources. The complexity of the problem.
However, before the project starts, the business needs to know how much the data distance can be synchronized, and make any necessary amendments to make it synchronize. The first step needs to create a statement that shows the universal data of those data of those data. , And verify its value, highlight the records that do not meet the conditions. There is a short Abstract here:
annotation
After a while of scrutiny and some ideas, I decided to use annotations to drive the configuration of data comparison and report processing. What we need is simple, and highly flexible and expanded. These annotations will be field -level level levels. And I like the configuration will not be hidden in a file in a certain place of ClassPath. In this way, you can directly view the annotations associated with the same field in order to know how it is processed.
In the simplest case, the annotation is nothing more than a mark, just to provide information that provides information without the operation of code execution itself. If you have been engaged in Java programming, then your use of them should be quite like now. You are familiar, but you may never have the need to create your own annotation. To this end, you need to create a new type with a Java type @Interface, which will include elements that can specify the detailed information of metadata.
Here is an example from this project:
@Target (Elementtype.field) @RETENTIONPOLICY.Runtime) Public @Interface Reconfield { /*** value indicateds that or not the value of Specified Sources Should be compared or Will be used to display value or reference within a run. * * @Return the value if source should be compared, defaults to true. * / boolean comparesourcess () default true; OULD be used to display the value in the report. * * @Return the Format Specified, DEFAULTING to Native. * / RECONDISPLAYFORMAT DISPLAYFORMAT () DEFAULT RECONDISPLAYFORMAT.NATIVE; / ** * Value Indicates the ID Value of T HE Field use for matching source value up to the filed. * * @Return the id of the filed. * / String ID (); / ** * Value Indicates the Label that should be displayed in the report for the fire. n empty string. */ string label () default " ; / ** * value that indicors the source that should be compared for different. Pare () default {};}
This is the main annotation of how the driving data comparison process operates. The basic elements it contains can meet most of the needs of different data sources for comparison. @ReConfield can handle the more complicated comparison. Most needs, and more complicated cases we will discuss it later. Most of these elements are introduced in one -to -one notes in the code list. It should be noted that on our @Rangfield There are several key annotations.
@Target's annotation allows you to specify that your annotation should be used on that Java element. The possible target type is Annotation_Type, Constructor, Field, Local_variable, Package, Parameter and Type. He It is designated to the Field level.
@Retention, which allows you to specify when the annotation is effective. The possible values are class, runtime, and source. Because we will process this annotation at running, it is the value we need to set.
This data verification process will run a query for each database, and map the results to the entity bean that shows the entity bean of all fields for specific business record types. Specific fields and their value execution data comparison in each database. Therefore, let's see a few examples to understand how these annotations are used in different data comparison configurations.
In order to verify the existing values and only match the accurate matching of each data source, you only need to provide a field ID and the marking of the field on the report.
@Reconfield (ID = Customer_id, label = "Customer ID") Private String Customerid;
In order to show the value found in each data source, but without any data comparison, you may need to make the comparesourceS element and set the value to false.
@ReConfield (ID = name, label = "name", comparesources = false) Private string name;
In order to verify the value found in the designated data source, not all, you may use ElementSourceStocompare. Use this thing to show all the found values, but only compare the values found in the data source listed in the element. In this way, some data scenarios that are not stored in every data source can be processed. Reconsource is an enumeration type that contains data sources that can be used for comparison.
@ReConfield (ID = Private_placement_flag, Label = "Private Placement Flag", SourceStocompare = {reconsource.legacy, reconsource.pace} G Priveplacementflag;
Now we have met our basic needs, and we need to solve the problem of implementing the specified field for complex data comparison capabilities. To this end, we will create a second annotation to drive custom rules for processing.
@Target (ElementType.Field) @RETENTION (RetentionPolicy.runtime) Public @Interface reconcustomrule { /*** value indicotes the Parameters used to instantis ATE A Custom Rule Processor, The Default Value is No Parameters. ** @Return the String [] Of parameters to instantiated a custom run,* /String [] Params () default {}; /*** value indicates the class of the Custom Rulessor to be used in compay the value from each source. ** @Return the Class of the Custom Rule Processor.*/Class <?> Processor () default defaultReconrule.class;}
It is very similar to the previous annotations. The biggest difference is that we specify a class in the @Reconcustomrule annotation, which can perform data comparison during the reconstruction processing. You can instantiated and initialize the class you specified. The class specified in this annotation will need to implement a universal rule interface. It will be used by the rules processor to execute the rules.
Now let's take a look at the example of using this annotation.
In this example, we use a customized rule that will check whether the stock exchange is united states. If it is, this data will be skipped. For this reason, this rule will need to check the Exchange Country in the same record in the same record. Field.
@RECONFIELD (ID = Street_cusip, Label = "Street Cusip", Comparesources = FALSE) @ReConCustomrule (Processor = SkipnonUsexChangecomParisonRule.Class) ATE String Streetcusip;
Here we specify a parameter for custom rules. Here it is a capacity. For this special data comparison, the comparison value cannot be deviated from 1000. By using the parameter specified by the use of the capacity, we can then we can Use different tolerance to apply the same set of custom rules to multiple fields. The only disadvantage is that because of the nature of the annotation, these parameters can only be static, so they cannot be modified dynamically.
@ReConfield (ID = USD_MKT_CAP, Label = "Market Cap USD", DisplayFormat = RECONDISPLAYFORMAT.NUMERIC_WHOLE, SourceStocompare = {Reconsource.Legacy, Reconsource.pace, reconsource.bob_prcm})@RECONCUSTOMRULE (processor = toleranceamountRule.classs, params = {" 10000 "}) Private Bigdecimal USDMKTCAP;
As you can see, we only use a few simple annotations, and we have designed a data verification report function with a considerable degree of flexibility to a multi -data library scenario. In this special case, the annotation drives the comparison process of the data. Therefore, we actually use the annotation to calculate the mapping data entities found and use them directly for processing.