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 yesterday

























      asked yesterday









      pirho

      3,355101730




      3,355101730






















          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
            yesterday










          • Ah, sorry that method is in JpaRepository but not CrudRepository. Have updated my answer.
            – codemonkey
            yesterday

















          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






























            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
              yesterday










            • Ah, sorry that method is in JpaRepository but not CrudRepository. Have updated my answer.
              – codemonkey
              yesterday














            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
              yesterday










            • Ah, sorry that method is in JpaRepository but not CrudRepository. Have updated my answer.
              – codemonkey
              yesterday












            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 yesterday

























            answered yesterday









            codemonkey

            1,3253717




            1,3253717











            • 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
              yesterday










            • Ah, sorry that method is in JpaRepository but not CrudRepository. Have updated my answer.
              – codemonkey
              yesterday
















            • 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
              yesterday










            • Ah, sorry that method is in JpaRepository but not CrudRepository. Have updated my answer.
              – codemonkey
              yesterday















            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
            yesterday




            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
            yesterday












            Ah, sorry that method is in JpaRepository but not CrudRepository. Have updated my answer.
            – codemonkey
            yesterday




            Ah, sorry that method is in JpaRepository but not CrudRepository. Have updated my answer.
            – codemonkey
            yesterday












            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 yesterday









                pirho

                3,355101730




                3,355101730



























                     

                    draft saved


                    draft discarded















































                     


                    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














































































                    這個網誌中的熱門文章

                    How to read a connectionString WITH PROVIDER in .NET Core?

                    Node.js Script on GitHub Pages or Amazon S3

                    Museum of Modern and Contemporary Art of Trento and Rovereto