diff --git a/src/main/java/io/ebean/Ebean.java b/src/main/java/io/ebean/Ebean.java index 8bc2fb4e8..643e2179d 100644 --- a/src/main/java/io/ebean/Ebean.java +++ b/src/main/java/io/ebean/Ebean.java @@ -116,6 +116,7 @@ import java.util.concurrent.ConcurrentHashMap; */ public final class Ebean { private static final Logger logger = LoggerFactory.getLogger(Ebean.class); + static { EbeanVersion.getVersion(); // initalizes the version class and logs the version. } @@ -374,7 +375,7 @@ public final class Ebean { * Note that this provides an try finally alternative to using {@link #executeCall(TxScope, Callable)} or * {@link #execute(TxScope, Runnable)}. *

- * + *

*

REQUIRES_NEW example:

*
{@code
    * // Start a new transaction. If there is a current transaction
@@ -648,11 +649,46 @@ public final class Ebean {
    * This method checks the uniqueness of a bean. I.e. if the save will work. It will return the
    * properties that violates an unique / primary key. This may be done in an UI save action to
    * validate if the user has entered correct values.
-   *
+   * 

* Note: This method queries the DB for uniqueness of all indices, so do not use it in a batch update. + *

+ * Note: This checks only the root bean! + *

+ *

{@code
    *
-   * TODO: it checks only the root bean!
-   * @param bean
+   *   // there is a unique constraint on title
+   *
+   *   Document doc = new Document();
+   *   doc.setTitle("One flew over the cuckoo's nest");
+   *   doc.setBody("clashes with doc1");
+   *
+   *   Set properties = server().checkUniqueness(doc);
+   *
+   *   if (properties.isEmpty()) {
+   *     // it is unique ... carry on
+   *
+   *   } else {
+   *     // build a user friendly message
+   *     // to return message back to user
+   *
+   *     String uniqueProperties = properties.toString();
+   *
+   *     StringBuilder msg = new StringBuilder();
+   *
+   *     properties.forEach((it)-> {
+   *       Object propertyValue = it.getVal(doc);
+   *       String propertyName = it.getName();
+   *       msg.append(" property["+propertyName+"] value["+propertyValue+"]");
+   *     });
+   *
+   *     // uniqueProperties > [title]
+   *     //       custom msg > property[title] value[One flew over the cuckoo's nest]
+   *
+   *  }
+   *
+   * }
+ * + * @param bean The entity bean to check uniqueness on * @return a set of Properties if constraint validation was detected or empty list. */ @Nonnull diff --git a/src/main/java/io/ebean/EbeanServer.java b/src/main/java/io/ebean/EbeanServer.java index 3ac761a97..d8bead322 100644 --- a/src/main/java/io/ebean/EbeanServer.java +++ b/src/main/java/io/ebean/EbeanServer.java @@ -11,7 +11,6 @@ import io.ebean.text.json.JsonContext; import javax.annotation.Nonnull; import javax.annotation.Nullable; - import javax.persistence.NonUniqueResultException; import javax.persistence.OptimisticLockException; import javax.persistence.PersistenceException; @@ -1464,18 +1463,53 @@ public interface EbeanServer { /** * This method checks the uniqueness of a bean. I.e. if the save will work. It will return the - * properties that violates an unique / primary key. This may be done in an UI save action to + * properties that violates an unique / primary key. This may be done in an UI save action to * validate if the user has entered correct values. - * + *

* Note: This method queries the DB for uniqueness of all indices, so do not use it in a batch update. - * - * TODO: it checks only the root bean! - * @param bean + *

+ * Note: This checks only the root bean! + *

+ *

{@code
+   *
+   *   // there is a unique constraint on title
+   *
+   *   Document doc = new Document();
+   *   doc.setTitle("One flew over the cuckoo's nest");
+   *   doc.setBody("clashes with doc1");
+   *
+   *   Set properties = server().checkUniqueness(doc);
+   *
+   *   if (properties.isEmpty()) {
+   *     // it is unique ... carry on
+   *
+   *   } else {
+   *     // build a user friendly message
+   *     // to return message back to user
+   *
+   *     String uniqueProperties = properties.toString();
+   *
+   *     StringBuilder msg = new StringBuilder();
+   *
+   *     properties.forEach((it)-> {
+   *       Object propertyValue = it.getVal(doc);
+   *       String propertyName = it.getName();
+   *       msg.append(" property["+propertyName+"] value["+propertyValue+"]");
+   *     });
+   *
+   *     // uniqueProperties > [title]
+   *     //       custom msg > property[title] value[One flew over the cuckoo's nest]
+   *
+   *  }
+   *
+   * }
+ * + * @param bean The entity bean to check uniqueness on * @return a set of Properties if constraint validation was detected or empty list. */ @Nonnull Set checkUniqueness(Object bean); - + /** * Same as {@link #checkUniqueness(Object)}. but with given transaction. */ diff --git a/src/test/java/org/tests/insert/TestInsertCheckUnique.java b/src/test/java/org/tests/insert/TestInsertCheckUnique.java index 2cb230698..61884f35e 100644 --- a/src/test/java/org/tests/insert/TestInsertCheckUnique.java +++ b/src/test/java/org/tests/insert/TestInsertCheckUnique.java @@ -1,11 +1,13 @@ package org.tests.insert; import io.ebean.BaseTestCase; - +import io.ebean.plugin.Property; import org.junit.Before; import org.junit.Test; import org.tests.model.draftable.Document; +import java.util.Set; + import static org.assertj.core.api.Assertions.assertThat; public class TestInsertCheckUnique extends BaseTestCase { @@ -15,7 +17,7 @@ public class TestInsertCheckUnique extends BaseTestCase { server().find(Document.class).asDraft().where().contains("title", "UniqueKey").delete(); server().find(Document.class).asDraft().where().isNull("title").delete(); } - + @Test public void insert_duplicateKey() { server().beginTransaction(); @@ -32,7 +34,6 @@ public class TestInsertCheckUnique extends BaseTestCase { doc2.setBody("clashes with doc1"); assertThat(server().checkUniqueness(doc2)).isEmpty(); - ; server().publish(doc1.getClass(), doc1.getId()); @@ -41,7 +42,7 @@ public class TestInsertCheckUnique extends BaseTestCase { server().endTransaction(); } } - + @Test public void insert_duplicateNull() { server().beginTransaction(); @@ -58,7 +59,7 @@ public class TestInsertCheckUnique extends BaseTestCase { doc2.setBody("clashes with doc1"); assertThat(server().checkUniqueness(doc2)).isEmpty(); - + server().publish(doc1.getClass(), doc1.getId()); assertThat(server().checkUniqueness(doc2)).isEmpty(); @@ -70,4 +71,48 @@ public class TestInsertCheckUnique extends BaseTestCase { } } + @Test + public void example() { + + server().beginTransaction(); + try { + Document doc1 = new Document(); + doc1.setTitle("One flew over the cuckoo's nest"); + doc1.setBody("one"); + doc1.save(); + + server().publish(doc1.getClass(), doc1.getId()); + + Document doc2 = new Document(); + doc2.setTitle("One flew over the cuckoo's nest"); + doc2.setBody("clashes with doc1"); + + Set properties = server().checkUniqueness(doc2); + if (properties.isEmpty()) { + // it is unique ... carry on + } else { + // build a user friendly message + // to return message back to user + + String uniqueProperties = properties.toString(); + + StringBuilder msg = new StringBuilder(); + + properties.forEach((it)-> { + Object propertyValue = it.getVal(doc2); + String propertyName = it.getName(); + msg.append(" property["+propertyName+"] value["+propertyValue+"]"); + }); + + System.out.println("uniqueProperties > "+uniqueProperties); + System.out.println(" custom msg > " + msg.toString()); + + } + + + assertThat(server().checkUniqueness(doc2).toString()).contains("title"); + } finally { + server().endTransaction(); + } + } }