Unable to generate constraint violation exception when testing Hibernate @Check constraints









up vote
1
down vote

favorite












I am playing with Hibernate @Check annotation but can not have my test fail when constraints are not satisfied. Currently just using default Spring boot configuration with H2 database.



What am I missing? Should there be a some kind of a flush after save(..)?



When running test I see the table created correctly. If I copy the creation line from the log and using it create a table to my 'real' Postgres database I can test different inserts and see that this line is all fine with constraints.



Entity



@Getter @Setter
@Entity @Check(constraints = "a IS NOT NULL OR b IS NOT NULL")
public class Constrained

@Id @GeneratedValue
private Long id;

private String a, b;



Test



@DataJpaTest
@RunWith(SpringRunner.class)
public class HibernateCheckTest

@Resource // this repo is just some boiler plate code but attached at
// the bottom of question
private ConstrainedRepository repo;

@Test @Transactional // also tried without @Transactional
public void test()
Constrained c = new Constrained();
repo.save(c); // Am I wrong to expect some constraint exception here?




Table generation script while running test




create table constrained (id bigint not null, a varchar(255), b
varchar(255), primary key (id), check (a IS NOT NULL OR b IS NOT
NULL))




Repository (not much to see in repo but just to show it):



public interface ConstrainedRepository
extends CrudRepository<Constrained, Long>



HOWEVER



If I use EntityManager so adding to my test class:



@PersistenceContext
private EntityManager em;


and doing the persist like:



em.persist(c);
em.flush();


instead of repo.save(c) I will get the exception.



AND



studying the log from the original test with repo.save(c) more careful shows:




org.springframework.test.context.transaction.TransactionContext:139 - Rolled back transaction for test:

...

testException = [null],




so for some reason this error is just wrapped and logged. How to have it "unwrapped" and thrown when using repository for persisting?










share|improve this question



























    up vote
    1
    down vote

    favorite












    I am playing with Hibernate @Check annotation but can not have my test fail when constraints are not satisfied. Currently just using default Spring boot configuration with H2 database.



    What am I missing? Should there be a some kind of a flush after save(..)?



    When running test I see the table created correctly. If I copy the creation line from the log and using it create a table to my 'real' Postgres database I can test different inserts and see that this line is all fine with constraints.



    Entity



    @Getter @Setter
    @Entity @Check(constraints = "a IS NOT NULL OR b IS NOT NULL")
    public class Constrained

    @Id @GeneratedValue
    private Long id;

    private String a, b;



    Test



    @DataJpaTest
    @RunWith(SpringRunner.class)
    public class HibernateCheckTest

    @Resource // this repo is just some boiler plate code but attached at
    // the bottom of question
    private ConstrainedRepository repo;

    @Test @Transactional // also tried without @Transactional
    public void test()
    Constrained c = new Constrained();
    repo.save(c); // Am I wrong to expect some constraint exception here?




    Table generation script while running test




    create table constrained (id bigint not null, a varchar(255), b
    varchar(255), primary key (id), check (a IS NOT NULL OR b IS NOT
    NULL))




    Repository (not much to see in repo but just to show it):



    public interface ConstrainedRepository
    extends CrudRepository<Constrained, Long>



    HOWEVER



    If I use EntityManager so adding to my test class:



    @PersistenceContext
    private EntityManager em;


    and doing the persist like:



    em.persist(c);
    em.flush();


    instead of repo.save(c) I will get the exception.



    AND



    studying the log from the original test with repo.save(c) more careful shows:




    org.springframework.test.context.transaction.TransactionContext:139 - Rolled back transaction for test:

    ...

    testException = [null],




    so for some reason this error is just wrapped and logged. How to have it "unwrapped" and thrown when using repository for persisting?










    share|improve this question

























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      I am playing with Hibernate @Check annotation but can not have my test fail when constraints are not satisfied. Currently just using default Spring boot configuration with H2 database.



      What am I missing? Should there be a some kind of a flush after save(..)?



      When running test I see the table created correctly. If I copy the creation line from the log and using it create a table to my 'real' Postgres database I can test different inserts and see that this line is all fine with constraints.



      Entity



      @Getter @Setter
      @Entity @Check(constraints = "a IS NOT NULL OR b IS NOT NULL")
      public class Constrained

      @Id @GeneratedValue
      private Long id;

      private String a, b;



      Test



      @DataJpaTest
      @RunWith(SpringRunner.class)
      public class HibernateCheckTest

      @Resource // this repo is just some boiler plate code but attached at
      // the bottom of question
      private ConstrainedRepository repo;

      @Test @Transactional // also tried without @Transactional
      public void test()
      Constrained c = new Constrained();
      repo.save(c); // Am I wrong to expect some constraint exception here?




      Table generation script while running test




      create table constrained (id bigint not null, a varchar(255), b
      varchar(255), primary key (id), check (a IS NOT NULL OR b IS NOT
      NULL))




      Repository (not much to see in repo but just to show it):



      public interface ConstrainedRepository
      extends CrudRepository<Constrained, Long>



      HOWEVER



      If I use EntityManager so adding to my test class:



      @PersistenceContext
      private EntityManager em;


      and doing the persist like:



      em.persist(c);
      em.flush();


      instead of repo.save(c) I will get the exception.



      AND



      studying the log from the original test with repo.save(c) more careful shows:




      org.springframework.test.context.transaction.TransactionContext:139 - Rolled back transaction for test:

      ...

      testException = [null],




      so for some reason this error is just wrapped and logged. How to have it "unwrapped" and thrown when using repository for persisting?










      share|improve this question















      I am playing with Hibernate @Check annotation but can not have my test fail when constraints are not satisfied. Currently just using default Spring boot configuration with H2 database.



      What am I missing? Should there be a some kind of a flush after save(..)?



      When running test I see the table created correctly. If I copy the creation line from the log and using it create a table to my 'real' Postgres database I can test different inserts and see that this line is all fine with constraints.



      Entity



      @Getter @Setter
      @Entity @Check(constraints = "a IS NOT NULL OR b IS NOT NULL")
      public class Constrained

      @Id @GeneratedValue
      private Long id;

      private String a, b;



      Test



      @DataJpaTest
      @RunWith(SpringRunner.class)
      public class HibernateCheckTest

      @Resource // this repo is just some boiler plate code but attached at
      // the bottom of question
      private ConstrainedRepository repo;

      @Test @Transactional // also tried without @Transactional
      public void test()
      Constrained c = new Constrained();
      repo.save(c); // Am I wrong to expect some constraint exception here?




      Table generation script while running test




      create table constrained (id bigint not null, a varchar(255), b
      varchar(255), primary key (id), check (a IS NOT NULL OR b IS NOT
      NULL))




      Repository (not much to see in repo but just to show it):



      public interface ConstrainedRepository
      extends CrudRepository<Constrained, Long>



      HOWEVER



      If I use EntityManager so adding to my test class:



      @PersistenceContext
      private EntityManager em;


      and doing the persist like:



      em.persist(c);
      em.flush();


      instead of repo.save(c) I will get the exception.



      AND



      studying the log from the original test with repo.save(c) more careful shows:




      org.springframework.test.context.transaction.TransactionContext:139 - Rolled back transaction for test:

      ...

      testException = [null],




      so for some reason this error is just wrapped and logged. How to have it "unwrapped" and thrown when using repository for persisting?







      java hibernate spring-boot jpa h2






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 10 at 10:28

























      asked Nov 10 at 9:10









      pirho

      3,590101830




      3,590101830






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          2
          down vote













          In ConstrainedRepository, extend JpaRepository instead of CrudRepository then use:



          repo.saveAndFlush(c);


          instead of:



          repo.save(c);


          The check is enforced in the database and that only happens when the changes (in this case an INSERT statement) are flushed to the database.



          Without an explicit flush, Hibernate will defer sending the statements to the database until the transaction is committed or a query is executed.



          However, from the Spring DataJpaTest documentation:




          By default, data JPA tests are transactional and roll back at the end
          of each test.




          So, in this case, there is not commit. The transaction is rolled back and the statements are never flushed to the database, and therefore the exception is never thrown.






          share|improve this answer






















          • Thanks. I would have assumed something like that. I have seen this method in some Q&As but my problem now is that my repos do not contain that method? Should i construct myt repo or test somehow differently? (i'm browsing the docs also but if you know quick answer)
            – pirho
            Nov 10 at 10:54










          • Ah, sorry that method is in JpaRepository but not CrudRepository. Have updated my answer.
            – codemonkey
            Nov 10 at 11:15

















          up vote
          1
          down vote













          Thanks to the answer from codemonkey I was able to find a solution. This resolves by adding:



          @org.springframework.transaction.annotation.Transactional(propagation = 
          Propagation.NOT_SUPPORTED)


          to my test class.






          share|improve this answer




















            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53237507%2funable-to-generate-constraint-violation-exception-when-testing-hibernate-check%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            2
            down vote













            In ConstrainedRepository, extend JpaRepository instead of CrudRepository then use:



            repo.saveAndFlush(c);


            instead of:



            repo.save(c);


            The check is enforced in the database and that only happens when the changes (in this case an INSERT statement) are flushed to the database.



            Without an explicit flush, Hibernate will defer sending the statements to the database until the transaction is committed or a query is executed.



            However, from the Spring DataJpaTest documentation:




            By default, data JPA tests are transactional and roll back at the end
            of each test.




            So, in this case, there is not commit. The transaction is rolled back and the statements are never flushed to the database, and therefore the exception is never thrown.






            share|improve this answer






















            • Thanks. I would have assumed something like that. I have seen this method in some Q&As but my problem now is that my repos do not contain that method? Should i construct myt repo or test somehow differently? (i'm browsing the docs also but if you know quick answer)
              – pirho
              Nov 10 at 10:54










            • Ah, sorry that method is in JpaRepository but not CrudRepository. Have updated my answer.
              – codemonkey
              Nov 10 at 11:15














            up vote
            2
            down vote













            In ConstrainedRepository, extend JpaRepository instead of CrudRepository then use:



            repo.saveAndFlush(c);


            instead of:



            repo.save(c);


            The check is enforced in the database and that only happens when the changes (in this case an INSERT statement) are flushed to the database.



            Without an explicit flush, Hibernate will defer sending the statements to the database until the transaction is committed or a query is executed.



            However, from the Spring DataJpaTest documentation:




            By default, data JPA tests are transactional and roll back at the end
            of each test.




            So, in this case, there is not commit. The transaction is rolled back and the statements are never flushed to the database, and therefore the exception is never thrown.






            share|improve this answer






















            • Thanks. I would have assumed something like that. I have seen this method in some Q&As but my problem now is that my repos do not contain that method? Should i construct myt repo or test somehow differently? (i'm browsing the docs also but if you know quick answer)
              – pirho
              Nov 10 at 10:54










            • Ah, sorry that method is in JpaRepository but not CrudRepository. Have updated my answer.
              – codemonkey
              Nov 10 at 11:15












            up vote
            2
            down vote










            up vote
            2
            down vote









            In ConstrainedRepository, extend JpaRepository instead of CrudRepository then use:



            repo.saveAndFlush(c);


            instead of:



            repo.save(c);


            The check is enforced in the database and that only happens when the changes (in this case an INSERT statement) are flushed to the database.



            Without an explicit flush, Hibernate will defer sending the statements to the database until the transaction is committed or a query is executed.



            However, from the Spring DataJpaTest documentation:




            By default, data JPA tests are transactional and roll back at the end
            of each test.




            So, in this case, there is not commit. The transaction is rolled back and the statements are never flushed to the database, and therefore the exception is never thrown.






            share|improve this answer














            In ConstrainedRepository, extend JpaRepository instead of CrudRepository then use:



            repo.saveAndFlush(c);


            instead of:



            repo.save(c);


            The check is enforced in the database and that only happens when the changes (in this case an INSERT statement) are flushed to the database.



            Without an explicit flush, Hibernate will defer sending the statements to the database until the transaction is committed or a query is executed.



            However, from the Spring DataJpaTest documentation:




            By default, data JPA tests are transactional and roll back at the end
            of each test.




            So, in this case, there is not commit. The transaction is rolled back and the statements are never flushed to the database, and therefore the exception is never thrown.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 10 at 11:14

























            answered Nov 10 at 10:49









            codemonkey

            1,4203717




            1,4203717











            • Thanks. I would have assumed something like that. I have seen this method in some Q&As but my problem now is that my repos do not contain that method? Should i construct myt repo or test somehow differently? (i'm browsing the docs also but if you know quick answer)
              – pirho
              Nov 10 at 10:54










            • Ah, sorry that method is in JpaRepository but not CrudRepository. Have updated my answer.
              – codemonkey
              Nov 10 at 11:15
















            • Thanks. I would have assumed something like that. I have seen this method in some Q&As but my problem now is that my repos do not contain that method? Should i construct myt repo or test somehow differently? (i'm browsing the docs also but if you know quick answer)
              – pirho
              Nov 10 at 10:54










            • Ah, sorry that method is in JpaRepository but not CrudRepository. Have updated my answer.
              – codemonkey
              Nov 10 at 11:15















            Thanks. I would have assumed something like that. I have seen this method in some Q&As but my problem now is that my repos do not contain that method? Should i construct myt repo or test somehow differently? (i'm browsing the docs also but if you know quick answer)
            – pirho
            Nov 10 at 10:54




            Thanks. I would have assumed something like that. I have seen this method in some Q&As but my problem now is that my repos do not contain that method? Should i construct myt repo or test somehow differently? (i'm browsing the docs also but if you know quick answer)
            – pirho
            Nov 10 at 10:54












            Ah, sorry that method is in JpaRepository but not CrudRepository. Have updated my answer.
            – codemonkey
            Nov 10 at 11:15




            Ah, sorry that method is in JpaRepository but not CrudRepository. Have updated my answer.
            – codemonkey
            Nov 10 at 11:15












            up vote
            1
            down vote













            Thanks to the answer from codemonkey I was able to find a solution. This resolves by adding:



            @org.springframework.transaction.annotation.Transactional(propagation = 
            Propagation.NOT_SUPPORTED)


            to my test class.






            share|improve this answer
























              up vote
              1
              down vote













              Thanks to the answer from codemonkey I was able to find a solution. This resolves by adding:



              @org.springframework.transaction.annotation.Transactional(propagation = 
              Propagation.NOT_SUPPORTED)


              to my test class.






              share|improve this answer






















                up vote
                1
                down vote










                up vote
                1
                down vote









                Thanks to the answer from codemonkey I was able to find a solution. This resolves by adding:



                @org.springframework.transaction.annotation.Transactional(propagation = 
                Propagation.NOT_SUPPORTED)


                to my test class.






                share|improve this answer












                Thanks to the answer from codemonkey I was able to find a solution. This resolves by adding:



                @org.springframework.transaction.annotation.Transactional(propagation = 
                Propagation.NOT_SUPPORTED)


                to my test class.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 10 at 11:00









                pirho

                3,590101830




                3,590101830



























                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53237507%2funable-to-generate-constraint-violation-exception-when-testing-hibernate-check%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Use pre created SQLite database for Android project in kotlin

                    Darth Vader #20

                    Ondo