1 2 Previous Next 16 Replies Latest reply on Sep 13, 2009 1:45 PM by Eugene Goroschenya

    ManyToOne reference without @Audited annotation

    Marcin Tatarski Newbie

      I have an annotated (with @Audited) entity class (lets say - class A) in which I am using ManyToOne reference to another class (lets named this class as B).

      For various reason, I do not want to mark class B as @Audited class, because B is a static dictionary class with milion of records, so duplications in the Audited table is no possible.

      For now there is exception that the B class must be marked as @Audited.

      Is there any way to implement such a configuration in present Envers version (1.2.1)? Is this feature planned?

      I see such a configuration to work like in the @Audited class (I mean in te historic version of this class A_AUD) I will have ManyToOne reference to the non-audited class B.

      Is there any workaround to solve this problem?

        • 1. Re: ManyToOne reference without @Audited annotation
          Adam Warski Master

          Hello,

          this is unfortunately not currently possible - but I guess it's the most requested feature right now ;). So I'll try to add it soon - or maybe you would like to try?

          Adam

          • 2. Re: ManyToOne reference without @Audited annotation
            Marcin Tatarski Newbie

            Adam, we are going to implement this feature and provide the patch as well.

            Related Jira issue: http://opensource.atlassian.com/projects/hibernate/browse/HHH-4010

            • 3. Re: ManyToOne reference without @Audited annotation
              Adam Warski Master

              Great :)
              If you need any help, code pointers etc, let me know either here or via e-mail.

              Adam

              • 5. Re: ManyToOne reference without @Audited annotation
                Varun Mehta Newbie

                Shouldn't the annotation @NotAudited on the @ManyToOne take care of it ?

                class A {
                 B b;
                
                 @ManyToOne
                 @JoinColumn(name = "a_b_id")
                 @NotAudited
                 getB() {
                 // bla bla
                 }
                }


                @NotAudited
                When applied to a field, indicates that this field should not be audited.


                I has the same use case and I applied these annotation and envers stopped complaining. I referred to this ticket;
                http://opensource.atlassian.com/projects/hibernate/browse/HHH-3779

                • 6. Re: ManyToOne reference without @Audited annotation
                  Adam Warski Master

                  Hello,

                  thanks a lot! I'll apply it when I get some free time :)

                  Adam

                  • 7. Re: ManyToOne reference without @Audited annotation
                    Varun Mehta Newbie

                     

                    "varunmehta" wrote:
                    Shouldn't the annotation @NotAudited on the @ManyToOne take care of it ?


                    Answering my own question, yes and no.

                    Yes: Provided you don't want the relation to be audited
                    No: If you want the relation to be audited.

                    This is most important line to be understood.
                    If there is a need to have assiociation property audited, which target is not audited class/object, simply annotate such property

                    Means, if A is audited, B is not and in A you have;
                    @ManyToOne
                     @JoinColumn(name = "b_id")
                     getB() {
                     // bla bla
                     }


                    so if you want to audit the column b_id in A, then follow the solution mtatarski provided, if you are not interested in auditing the column at all, then use @NotAudited, but when you do that, fetching a.getB() will result in null, as the relation was never stored!

                    Hope that makes sense took me some time to figure out.

                    • 8. Re: ManyToOne reference without @Audited annotation
                      Adam Warski Master

                      Applied, thanks a lot! The patch was really great :)
                      One small thing I changed is rename the "targetAuditMode" to "relationTargetAuditMode" to make it more clear what it means - I was a bit confused myself at the beginning.

                      Adam

                      • 9. Re: ManyToOne reference without @Audited annotation
                        Varun Mehta Newbie

                        Adam,

                        I tried the patch too, but it was misbehaving for composite Ids. Where can I download the applied patch code.

                        • 10. Re: ManyToOne reference without @Audited annotation
                          Varun Mehta Newbie

                          ok, I got the code from http://anonsvn.jboss.org/repos/hibernate/core/branches/envers-hibernate-3.3/

                          3 Test cases failed;

                          org.hibernate.envers.test.integration.primitive.PrimitiveAddDelete.testHistoryOfId1
                          org.hibernate.envers.test.integration.primitive.PrimitiveAddDelete.testRevisionsCount
                          org.hibernate.envers.test.integration.reventity.ExceptionListener.testTransactionRollback


                          Here is the stacktrace.

                          java.lang.NullPointerException
                           at org.hibernate.envers.test.integration.primitive.PrimitiveAddDelete.testHistoryOfId1(PrimitiveAddDelete.java:81)
                           at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                           at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                           at java.lang.reflect.Method.invoke(Method.java:597)
                           at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:607)
                           at org.testng.internal.Invoker.invokeMethod(Invoker.java:517)
                           at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:669)
                           at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:956)
                           at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:126)
                           at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:110)
                           at org.testng.TestRunner.runWorkers(TestRunner.java:759)
                           at org.testng.TestRunner.privateRun(TestRunner.java:592)
                           at org.testng.TestRunner.run(TestRunner.java:486)
                           at org.testng.SuiteRunner.runTest(SuiteRunner.java:332)
                           at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:327)
                           at org.testng.SuiteRunner.privateRun(SuiteRunner.java:299)
                           at org.testng.SuiteRunner.run(SuiteRunner.java:204)
                           at org.testng.TestNG.createAndRunSuiteRunners(TestNG.java:877)
                           at org.testng.TestNG.runSuitesLocally(TestNG.java:842)
                           at org.testng.TestNG.run(TestNG.java:751)
                           at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:73)
                           at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:124)
                          ------------------------------------------------------------
                          java.lang.AssertionError
                           at org.hibernate.envers.test.integration.primitive.PrimitiveAddDelete.testRevisionsCounts(PrimitiveAddDelete.java:73)
                           at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                           at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                           at java.lang.reflect.Method.invoke(Method.java:597)
                           at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:607)
                           at org.testng.internal.Invoker.invokeMethod(Invoker.java:517)
                           at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:669)
                           at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:956)
                           at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:126)
                           at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:110)
                           at org.testng.TestRunner.runWorkers(TestRunner.java:759)
                           at org.testng.TestRunner.privateRun(TestRunner.java:592)
                           at org.testng.TestRunner.run(TestRunner.java:486)
                           at org.testng.SuiteRunner.runTest(SuiteRunner.java:332)
                           at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:327)
                           at org.testng.SuiteRunner.privateRun(SuiteRunner.java:299)
                           at org.testng.SuiteRunner.run(SuiteRunner.java:204)
                           at org.testng.TestNG.createAndRunSuiteRunners(TestNG.java:877)
                           at org.testng.TestNG.runSuitesLocally(TestNG.java:842)
                           at org.testng.TestNG.run(TestNG.java:751)
                           at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:73)
                           at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:124)
                          ------------------------------------------------------------
                          javax.persistence.RollbackException: Error while commiting the transaction
                           at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:71)
                           at org.hibernate.envers.test.integration.reventity.ExceptionListener.testTransactionRollback(ExceptionListener.java:51)
                           at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                           at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                           at java.lang.reflect.Method.invoke(Method.java:597)
                           at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:607)
                           at org.testng.internal.Invoker.invokeMethod(Invoker.java:517)
                           at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:669)
                           at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:956)
                           at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:126)
                           at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:110)
                           at org.testng.TestRunner.runWorkers(TestRunner.java:759)
                           at org.testng.TestRunner.privateRun(TestRunner.java:592)
                           at org.testng.TestRunner.run(TestRunner.java:486)
                           at org.testng.SuiteRunner.runTest(SuiteRunner.java:332)
                           at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:327)
                           at org.testng.SuiteRunner.privateRun(SuiteRunner.java:299)
                           at org.testng.SuiteRunner.run(SuiteRunner.java:204)
                           at org.testng.TestNG.createAndRunSuiteRunners(TestNG.java:877)
                           at org.testng.TestNG.runSuitesLocally(TestNG.java:842)
                           at org.testng.TestNG.run(TestNG.java:751)
                           at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:73)
                           at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:124)
                          Caused by: org.hibernate.TransactionException: JDBC commit failed
                           at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:161)
                           at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)
                           ... 23 more
                          Caused by: java.sql.SQLException: Can't call commit when autocommit=true
                           at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:930)
                           at com.mysql.jdbc.ConnectionImpl.commit(ConnectionImpl.java:1552)
                           at org.hibernate.transaction.JDBCTransaction.commitAndResetAutoCommit(JDBCTransaction.java:170)
                           at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:146)
                           ... 24 more


                          When I generated a jar out of this code, I get an error registering composite Ids;

                          IdMetadataGenerator:
                          // lines 96 - 105
                          
                           } else if (id_prop.isComposite()) {
                           // Embedded id
                          
                           Component id_component = (Component) id_prop.getValue();
                          
                           mapper = new EmbeddedIdMapper(getIdPropertyData(id_prop), id_component.getComponentClassName());
                           addIdProperties(rel_id_mapping, (Iterator<Property>) id_component.getPropertyIterator(), mapper, false);
                          
                           // null mapper - the mapping where already added the first time, now we only want to generate the xml
                           addIdProperties(orig_id_mapping, (Iterator<Property>) id_component.getPropertyIterator(), null, true);


                          And then the method, addIdProperties fails when checking propertyType instance of..

                          @SuppressWarnings({"unchecked"})
                           private void addIdProperties(Element parent, Iterator<Property> properties, SimpleMapperBuilder mapper, boolean key) {
                           while (properties.hasNext()) {
                           Property property = properties.next();
                           Type propertyType = property.getType();
                           if (!"_identifierMapper".equals(property.getName())) {
                           if (propertyType instanceof ImmutableType) {
                           // Last but one parameter: ids are always insertable
                           mainGenerator.getBasicMetadataGenerator().addBasic(parent,
                           getIdPersistentPropertyAuditingData(property),
                           property.getValue(), mapper, true, key);
                           } else {
                           throw new MappingException("Type not supported: " + propertyType.getClass().getName());
                           }
                           }
                           }
                           }


                          I'm going to try again, but let me know if you are already aware of the problem and have a solution.

                          • 11. Re: ManyToOne reference without @Audited annotation
                            Varun Mehta Newbie

                            My bad, damn should have checked my code before posting this issue. The test cases still fails;

                            Composite keys were failing cos I had marked one of them as

                            static


                            • 12. Re: ManyToOne reference without @Audited annotation
                              Varun Mehta Newbie

                              Ok I'm too sleepy working too late, it was a different code base I was testing on, works for primitive Objects marked for @Embeddable but not classes, will try adding new test cases.

                              • 13. Re: ManyToOne reference without @Audited annotation
                                Varun Mehta Newbie

                                 

                                "varunmehta" wrote:
                                My bad, damn should have checked my code before posting this issue. The test cases still fails;

                                Composite keys were failing cos I had marked one of them as
                                static


                                Did not work, I was looking at the wrong code base (older version of the envers jar), If you have Primitives as Composite Keys it works, but when you use classes they complain.

                                Caused by: org.hibernate.MappingException: Type not supported: org.hibernate.type.ManyToOneType
                                 at org.hibernate.envers.configuration.metadata.IdMetadataGenerator.addIdProperties(IdMetadataGenerator.java:71)
                                 at org.hibernate.envers.configuration.metadata.IdMetadataGenerator.addId(IdMetadataGenerator.java:102)
                                 at org.hibernate.envers.configuration.metadata.AuditMetadataGenerator.generateFirstPass(AuditMetadataGenerator.java:329)
                                 at org.hibernate.envers.configuration.EntitiesConfigurator.configure(EntitiesConfigurator.java:91)
                                 at org.hibernate.envers.configuration.AuditConfiguration.<init>(AuditConfiguration.java:86)
                                 at org.hibernate.envers.configuration.AuditConfiguration.getFor(AuditConfiguration.java:99)
                                 at org.hibernate.envers.event.AuditEventListener.initialize(AuditEventListener.java:260)
                                 at org.hibernate.event.EventListeners$1.processListener(EventListeners.java:198)
                                 at org.hibernate.event.EventListeners.processListeners(EventListeners.java:181)
                                 at org.hibernate.event.EventListeners.initializeListeners(EventListeners.java:194)
                                 ... 41 more


                                The mapping of my classes are such;

                                @Entity
                                public class Order {
                                 @Id
                                 private int orderId;
                                }
                                
                                @Entity
                                public class User {
                                 @Id
                                 private int userId;
                                }
                                
                                @Entity
                                public class Salesperson {
                                 @EmbeddedId
                                 private SalespersonPK salespersonPK;
                                }
                                
                                @Embeddable
                                public class SalespersonPK {
                                @ManyToOne
                                 private Order order;
                                
                                @ManyToOne
                                 private User user;
                                }


                                So when a Composite key of two objects is used, it fails, Is this mapping valid (I believe so), or org.hibernate.MappingException: Type not supported: org.hibernate.type.ManyToOneType should be checked for ImmutableTypes. Please suggest.

                                None of them are Audited for now, nor will I audit them, other classes are getting audited, but running the test cases causes the context load to fail.

                                • 14. Re: ManyToOne reference without @Audited annotation
                                  Varun Mehta Newbie

                                  Adding this fixed the ManytoOneType issue

                                  if (!"_identifierMapper".equals(property.getName())) {
                                   if (propertyType instanceof ImmutableType) {
                                   // Last but one parameter: ids are always insertable
                                   mainGenerator.getBasicMetadataGenerator().addBasic(parent,
                                   getIdPersistentPropertyAuditingData(property),
                                   property.getValue(), mapper, true, key);
                                   } else if (propertyType instanceof EntityType) {
                                   // Last but one parameter: ids are always insertable
                                   mainGenerator.getBasicMetadataGenerator().addBasic(parent,
                                   getIdPersistentPropertyAuditingData(property),
                                   property.getValue(), mapper, true, key);
                                   } else {


                                  But this solution correct, if so let me know I'll provide it as a patch.

                                  1 2 Previous Next