| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you 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. |
| --> |
| |
| ## SetEntity methods |
| |
| Annotate a DAO method with [@SetEntity] to fill a core driver data structure from an |
| [Entity](../../entities): |
| |
| ```java |
| public interface ProductDao { |
| @SetEntity |
| BoundStatement bind(Product product, BoundStatement boundStatement); |
| } |
| ``` |
| |
| The generated code will set each entity property on the target, such as: |
| |
| ```java |
| boundStatement = boundStatement.set("id", product.getId(), UUID.class); |
| boundStatement = boundStatement.set("description", product.getDescription(), String.class); |
| ... |
| ``` |
| |
| It does not perform a query. Instead, those methods are intended for cases where you will execute |
| the query yourself, and just need the conversion logic. |
| |
| ### Lenient mode |
| |
| By default, the mapper operates in "strict" mode: the target statement must contain a matching |
| column for every property in the entity definition, *except computed ones*. If such a column is not |
| found, an error will be thrown. |
| |
| Starting with driver 4.12.0, the `@SetEntity` annotation has a new `lenient` attribute. If this |
| attribute is explicitly set to `true`, the mapper will operate in "lenient" mode: all entity |
| properties that have a matching column in the target statement will be set. However, *unmatched |
| properties will be left untouched*. |
| |
| As an example to illustrate how lenient mode works, assume that we have the following entity and |
| DAO: |
| |
| ```java |
| @Entity class Product { |
| |
| @PartitionKey int id; |
| String description; |
| float price; |
| // other members omitted |
| } |
| |
| interface ProductDao { |
| |
| @SetEntity(lenient = true) |
| BoundStatement setLenient(Product product, BoundStatement stmt); |
| |
| } |
| ``` |
| |
| Then the following code would be possible: |
| |
| ```java |
| Product product = new Product(1, "scented candle", 12.99); |
| // stmt does not contain the price column |
| BoundStatement stmt = session.prepare("INSERT INTO product (id, description) VALUES (?, ?)").bind(); |
| stmt = productDao.setLenient(product, stmt); |
| ``` |
| |
| Since no `price` column was found in the target statement, `product.price` wasn't read (if the |
| statement is executed, the resulting row in the database will have a price of zero). Without lenient |
| mode, the code above would throw an error instead. |
| |
| Lenient mode allows to achieve the equivalent of driver 3.x [manual mapping |
| feature](https://docs.datastax.com/en/developer/java-driver/3.10/manual/object_mapper/using/#manual-mapping). |
| |
| **Beware that lenient mode may result in incomplete rows being inserted in the database.** |
| |
| ### Parameters |
| |
| The method must have two parameters: one is the entity instance, the other must be a subtype of |
| [SettableByName] \(the most likely candidates are [BoundStatement], [BoundStatementBuilder] and |
| [UdtValue]). Note that you can't use [SettableByName] itself. |
| |
| The order of the parameters does not matter. |
| |
| The annotation can define a [null saving strategy](../null_saving/) that applies to the properties |
| of the object to set. This is only really useful with bound statements (or bound statement |
| builders): if the target is a [UdtValue], the driver sends null fields in the serialized form |
| anyway, so both strategies are equivalent. |
| |
| ### Return type |
| |
| The method can either be void, or return the exact same type as its settable parameter. |
| |
| ```java |
| @SetEntity |
| void bind(Product product, UdtValue udtValue); |
| |
| @SetEntity |
| void bind(Product product, BoundStatementBuilder builder); |
| ``` |
| |
| Note that if the settable parameter is immutable, the method should return a new instance, because |
| the generated code won't be able to modify the argument in place. This is the case for |
| [BoundStatement], which is immutable in the driver: |
| |
| ```java |
| // Wrong: statement won't be modified |
| @SetEntity |
| void bind(Product product, BoundStatement statement); |
| |
| // Do this instead: |
| @SetEntity |
| BoundStatement bind(Product product, BoundStatement statement); |
| ``` |
| |
| If you use a void method with [BoundStatement], the mapper processor will issue a compile-time |
| warning. |
| |
| [@SetEntity]: https://docs.datastax.com/en/drivers/java/4.17/com/datastax/oss/driver/api/mapper/annotations/SetEntity.html |
| [BoundStatement]: https://docs.datastax.com/en/drivers/java/4.17/com/datastax/oss/driver/api/core/cql/BoundStatement.html |
| [BoundStatementBuilder]: https://docs.datastax.com/en/drivers/java/4.17/com/datastax/oss/driver/api/core/cql/BoundStatementBuilder.html |
| [SettableByName]: https://docs.datastax.com/en/drivers/java/4.17/com/datastax/oss/driver/api/core/data/SettableByName.html |
| [UdtValue]: https://docs.datastax.com/en/drivers/java/4.17/com/datastax/oss/driver/api/core/data/UdtValue.html |