Skip to content

Commit

Permalink
Merge pull request #282 from jakartaee/add-operation-annotations
Browse files Browse the repository at this point in the history
Adding CRUD Annotations for Dynamic Repositories
  • Loading branch information
otaviojava authored Oct 11, 2023
2 parents 799782b + 3ef795c commit 773562c
Show file tree
Hide file tree
Showing 4 changed files with 288 additions and 0 deletions.
63 changes: 63 additions & 0 deletions api/src/main/java/jakarta/data/repository/Delete.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2023 Contributors to the Eclipse Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package jakarta.data.repository;


import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* <p>The {@code Delete} annotation indicates that the annotated repository method requests one or more
* entities to be removed from the database. This method must have a single parameter whose type must be one of the following:
* </p>
* <ul>
* <li>The entity to be deleted.</li>
* <li>An {@code Iterable} of entities to be deleted.</li>
* <li>An array of entities to be deleted.</li>
* </ul>
* <p>The return type of the annotated method must be {@code void}, {@code boolean}, a numeric primitive type
* (such as {@code int}), or a corresponding primitive wrapper type (such as {@link Integer}).
* A boolean return type indicates whether or not an entity was deleted from the database.
* A numeric return type indicates how many entities were deleted from the database.
* </p>
* <p>Deletion of a given entity is performed by matching the entity's Id. If the entity is versioned (e.g.,
* with {@code jakarta.persistence.Version}), the version is also checked for consistency during deletion.
* Properties other than the Id and version do not need to match for deletion.
* </p>
* <p>For example, consider an interface representing a garage:</p>
* <pre>
* {@literal @}Repository
* interface Garage {
* {@literal @}Delete
* Car unpark(Car car);
* }
* </pre>
* * <p>If this annotation is combined with other operation annotations (e.g., {@code @Insert}, {@code @Update},
* * {@code @Save}), it will throw an {@link UnsupportedOperationException} as only one operation type can be specified.</p>
* <p>If the unique identifier of an entity is not found in the database or its version does not match, and the return
* type of the annotated method is {@code void} or {@code Void}, the method must
* raise {@link jakarta.data.exceptions.OptimisticLockingFailureException}.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Delete {
}
78 changes: 78 additions & 0 deletions api/src/main/java/jakarta/data/repository/Insert.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (c) 2023 Contributors to the Eclipse Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package jakarta.data.repository;


import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* <p>The {@code Insert} annotation indicates that the annotated repository method requests that one or more entities
* be inserted into the database. This method must have a single parameter whose type must be one of the following:
* </p>
* <ul>
* <li>The entity to be inserted.</li>
* <li>An {@code Iterable} of entities to be inserted.</li>
* <li>An array of entities to be inserted.</li>
* </ul>
* <p>The return type of an annotated method that requires a single entity as the parameter must have a return type
* that is {@code void}, {@code Void}, or the same type as the parameter.
* The return type of an annotated method that accepts an {@code Iterable} or array of entities as the parameter must
* have a return type that is {@code void}, {@code Void}, or an {@code Iterable} or array of the entity.
* For example, if the method is annotated with {@code @Insert} and takes a parameter of type {@code Car car},
* the return type can be {@code Car}.
* Similarly, if the parameter is an {@code Iterable<Car>} or an array of {@code Car}, the return type can be
* {@code Iterable<Car>}.
* Entities that are returned by the annotated method must include all values that were
* written to the database, including all automatically generated values and incremented values
* that changed due to the insert. The position of entities within an {@code Iterable} or array return value
* must correspond to the position of entities in the parameter based on the unique identifier of the entity.
* </p>
* <p>After invoking this method, it is recommended not to use the entity value supplied as a parameter, as this method
* makes no guarantees about the state of the entity value after insertion.
* </p>
* <p>If an entity of this type with the same unique identifier already exists in the database
* and the databases performs ACID (atomic, consistent, isolated, durable) transactions,
* then annotated method raises {@link jakarta.data.exceptions.EntityExistsException}.
* In databases that follow the BASE model or use an append model to write data,
* this exception is not thrown.
* </p>
* <p>For example, consider an interface representing a garage:</p>
* <pre>
* {@literal @}Repository
* interface Garage {
* {@literal @}Insert
* Car park(Car car);
* }
* </pre>
* <p>The {@code @Insert} annotation can be used to indicate that the {@code park(Car)} method is responsible for inserting
* a {@code Car} entity into a database.
* </p>
*
* <p>If this annotation is combined with other operation annotations (e.g., {@code @Update}, {@code @Delete},
* {@code @Save}), it will throw an {@link UnsupportedOperationException} because only one operation type can be specified.
* A Jakarta Data provider implementation must detect (and report) this error at compile time or at runtime.</p>
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Insert {
}
80 changes: 80 additions & 0 deletions api/src/main/java/jakarta/data/repository/Save.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (c) 2023 Contributors to the Eclipse Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package jakarta.data.repository;


import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* <p>The {@code Save} annotation indicates that the annotated repository method
* updates one or more entities if found in the database
* and inserts entities into the database that are not found.
* This method must have a single parameter whose type must be one of the following:
* </p>
* <ul>
* <li>The entity to be saved.</li>
* <li>An {@code Iterable} of entities to be saved.</li>
* <li>An array of entities to be saved.</li>
* </ul>
* <p>The return type of an annotated method that requires a single entity as the parameter
* must have a return type that is {@code void}, {@code Void}, or the same type as the parameter.
* The return type of an annotated method that accepts an {@code Iterable} or array of entities
* as the parameter must have a return type that is {@code void}, {@code Void},
* or an {@code Iterable} or array of the entity.
* </p>
* <p>Saving an entity involves persisting it in the database. If the entity has an ID or key that already exists
* in the database, the method will update the existing record. If the entity does not exist in the database or has a
* null ID, this method will insert a new record. The entity instance returned by this method will be updated with
* any automatically generated or incremented values that changed due to the save operation.
* </p>
* <p>Entities that are returned by the annotated method must include all values that were
* written to the database, including all automatically generated values and incremented values
* that changed due to the save. The position of entities within an {@code Iterable} or array return value
* must correspond to the position of entities in the parameter based on the unique identifier of the entity.</p>
* <p>After invoking this method, avoid using the entity value that was supplied as a parameter, because it might not accurately
* reflect the changes made during the save process. If the entity uses optimistic locking and its version differs from
* the version in the database, an {@link jakarta.data.exceptions.OptimisticLockingFailureException} will be thrown.
* </p>
*
* <p>For example, consider an interface representing a garage:</p>
* <pre>
* {@literal @}Repository
* interface Garage {
* {@literal @}Save
* Car park(Car car);
* }
* </pre>
* <p>The {@code @Save} annotation can be used to indicate that the {@code park(Car)} method is responsible
* for updating the entity in the database if it already exists there and otherwise inserting
* a car entity into a database.
* </p>
*
* <p>If this annotation is combined with other operation annotations (e.g., {@code @Update}, {@code @Delete},
* {@code @Insert}), it will throw an {@link UnsupportedOperationException} because only one operation type can be specified.
* A Jakarta Data provider implementation must detect (and report) this error at compile time or at runtime.</p>
* @see jakarta.data.exceptions.OptimisticLockingFailureException
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Save {
}
67 changes: 67 additions & 0 deletions api/src/main/java/jakarta/data/repository/Update.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2023 Contributors to the Eclipse Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package jakarta.data.repository;


import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


/**
* <p>The {@code Update} annotation indicates that the annotated repository method requests that one or more entities
* be updated if found in the database. This method must have a single parameter whose type must be one of the following:
* </p>
* <ul>
* <li>The entity to be updated.</li>
* <li>An {@code Iterable} of entities to be updated.</li>
* <li>An array of entities to be updated.</li>
* </ul>
* <p>The return type of the annotated method must be {@code void}, {@code boolean}, a numeric primitive type
* (such as {@code int}), or a corresponding primitive wrapper type (such as {@link Integer}).
* A boolean return type indicates whether a matching entity was found in the database to update.
* A numeric return type indicates how many matching entities were found in the database to update.
* </p>
* <p>Updating an entity involves modifying its existing data in the database. The method will search for the entity
* in the database using its ID (and version, if versioned) and then update the corresponding record with the new data. After invoking
* this method, do not continue to use the entity value that is supplied as a parameter, as it may not accurately
* reflect the changes made during the update process.
* </p>
* <p>If the entity does not exist in the database or it is versioned and its version differs from the version in the database,
* no update is made and no error is raised.
* </p>
*
* <p>For example, consider an interface representing a garage:</p>
* <pre>
* &#64;Repository
* interface Garage {
* {@literal @}Update
* Car update(Car car);
* }
* </pre>
* <p>If this annotation is combined with other operation annotations (e.g., {@code @Insert}, {@code @Delete},
* {@code @Save}), it will throw an {@link UnsupportedOperationException} because only one operation type can be specified.
* A Jakarta Data provider implementation must detect (and report) this error at compile time or at runtime.</p>
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Update {
}

0 comments on commit 773562c

Please sign in to comment.