-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 13 posts ] 
Author Message
 Post subject: OneToMany is not persisting children
PostPosted: Tue Feb 21, 2006 7:59 pm 
Beginner
Beginner

Joined: Wed Nov 30, 2005 10:25 pm
Posts: 25
Hibernate version: 3.1, Annotations 3.1 beta 8

Problem: Parent object contains children. I want to persist changes from the parent to the child, but not vice versa.

What works: Inserting and deleting of the parent

What breaks: Inserting a new child while updating the parent (child is not inserted)

Code:
Parent:

Code:
...
public class Folder
{
  @OnDelete(action=OnDeleteAction.CASCADE)
  @OneToMany(cascade=CascadeType.ALL, mappedBy="folder")
  private List<FolderTeamPermission> teamPermissions =
    new ArrayList<FolderTeamPermission>();
...

Child:
Code:
...
@SequenceGenerator(name="seq", sequenceName="C_Folder_TeamSecurity_Seq")
public class FolderTeamPermission
  implements TeamPermission<Folder>
{
  @Id
  @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq")
  private Integer id;

  @ManyToOne
  @JoinColumn(name="folderId")
  private Folder folder;

  @ManyToOne
  @JoinColumn(name="teamName")
  private SecurityTeam team;
...


Business code:
Code:
.. start tx
Folder folder = session.get(Folder.class, folderId);
FolderTeamPermission currTeamPerm = new FolderTeamPermission();
currTeamPerm.setFolder(folder);
currTeamPerm.setPermission(permission);
SecurityTeam team = session.get(SecurityFolder.class, teamName);
currTeamPerm.setTeam(team);
folder.getTeamPermissions().add(currTeamPerm);

folder.setLastModified(new Date());
... commit tx


At this point I have tried just commiting the transaction (which I thought should be enough), "session.saveOrUpdate(folder)" and "session.merge(folder)", but none cause an insert.

All I get in the SQL:
Code:
16:33:18,773 INFO  [STDOUT] Hibernate: select users0_.teamname as teamname1_, users0_.username as username1_, cpmuserbea1_.username as username18_0_, cpmuserbea1_.password as password18_0_, cpmuserbea1_.first_name as first3_18_0_, cpmuserbea1_.last_name as last4_18_0_, cpmuserbea1_.active_status as active5_18_0_, cpmuserbea1_.email_address as email6_18_0_ from spappset.S_Users_Teams users0_ left outer join spappset.S_Users cpmuserbea1_ on users0_.username=cpmuserbea1_.username where users0_.teamname=?
16:33:18,805 INFO  [STDOUT] Hibernate: update C_Folder set path=?, name=?, parentId=?, owner=?, lastModDt=?, createdDt=? where id=?


The folder is updated as you can see, but the permission that ties the folder to a security team is never inserted even though it was added to the list (Persistent bag).

If I am correct, there should be no reason for me to call "session.persist(currTeamPerm)", as the session should already know I inserted the item.

Is it the "mappedBy" attribute that is the problem, or is there something else I am missing.

I also saw this in the log, not sure if it is making the difference:

Code:
16:33:19,242 INFO  [SettingsFactory] Automatic flush during beforeCompletion(): disabled
16:33:19,242 INFO  [SettingsFactory] Automatic session close at end of transaction: disabled
16:33:19,242 INFO  [SettingsFactory] Scrollable result sets: disabled
16:33:19,243 INFO  [SettingsFactory] JDBC3 getGeneratedKeys(): disabled
16:33:19,243 INFO  [SettingsFactory] Connection release mode: auto
16:33:19,243 INFO  [SettingsFactory] Default batch fetch size: 1
16:33:19,243 INFO  [SettingsFactory] Generate SQL with comments: disabled
16:33:19,243 INFO  [SettingsFactory] Order SQL updates by primary key: disabled
16:33:19,243 INFO  [SettingsFactory] Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
16:33:19,243 INFO  [ASTQueryTranslatorFactory] Using ASTQueryTranslatorFactory
16:33:19,243 INFO  [SettingsFactory] Query language substitutions: {}
16:33:19,243 INFO  [SettingsFactory] Second-level cache: enabled
16:33:19,243 INFO  [SettingsFactory] Query cache: disabled
16:33:19,243 INFO  [SettingsFactory] Cache provider: org.hibernate.cache.EhCacheProvider
16:33:19,243 INFO  [SettingsFactory] Optimize cache for minimal puts: disabled
16:33:19,243 INFO  [SettingsFactory] Structured second-level cache entries: disabled
16:33:19,244 INFO  [SettingsFactory] Echoing all SQL to stdout
16:33:19,244 INFO  [SettingsFactory] Statistics: disabled
16:33:19,244 INFO  [SettingsFactory] Deleted entity synthetic identifier rollback: disabled
16:33:19,244 INFO  [SettingsFactory] Default entity-mode: pojo


I'm basically stuck. Any help appreciated (I never had this problem with the hibernate.hbm.xml files, so I may just not have mapped the annotations correctly). BTW - I am using the javax.persistence annotations when available and the hibernate annotations only when there are no corresponding javax ones. I am using SessionFactory/Session and not EntityManager to do the persistence.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 21, 2006 10:20 pm 
Expert
Expert

Joined: Mon Jan 09, 2006 5:01 pm
Posts: 311
Location: Sacramento, CA
old answer:
( try using cascade="save-update" on the <many-to-one ...> mapping. Which is different than what you have - you have it on your <one-to-many...)

new edited:

I went back to my code and noticed that if I took out the <many-to-one mapping of my relationship all together, and just had the <one-to-many and it still worked whereby I would get(Class,Id); and then did a merge, next I added a child object to its collection and did a saveOrUpdate()... It worked too. So I thought I'd post my code to you that is working, and you can see what might be different:

Here is the code for 1(Person)-to-Many(Address)

Code:
<class name="..Person">
...
<set
            name="ADDRESSES"
            lazy="false"
            cascade="all"
            sort="unsorted">

            <key
                column="PERSON_ID"
            >
            </key>

            <one-to-many
                  class="com.acme.hibernate.samples_1.Address"
            />

        </set>
</class>

<class name="...Address">
<!-- removed!
        <many-to-one
            name="person"
            class="com.acme.hibernate.samples_1.Person"
            cascade="save-update"
            outer-join="true"
            update="true"
            insert="true"
            column="PERSON_ID"
            not-null="false"
        />
-->
</class>


Java Code:
Code:
   p2=(Person) sess.get(Person.class,new Long(819200));
   sess.merge(p2);
   Address addr2=new Address();
   addr2.setSTREET("2299 Whipple St");
   addr2.setCITY("Redwood City");
   addr2.setSTATE("AK");
   addr2.setZIP("94063");
   p2.getADDRESSES().add(addr2);
   sess.saveOrUpdate(p2);


Hope this helps.

-JT
please rate (Y) on my response if this helped...thx.


Top
 Profile  
 
 Post subject: Doesn't work
PostPosted: Wed Feb 22, 2006 12:05 pm 
Beginner
Beginner

Joined: Wed Nov 30, 2005 10:25 pm
Posts: 25
That solution doesn't work. It still doesn't cascade the insert. I need the @ManyToOne as I need to navigate both directions. Basically I have a many-to-many with data in my M2M datable (the permission)

So I have in my database:
C_Folder ---> C_Folder_TeamSecurity <--- S_Teams

The team security just has a FK to folder and teams, but it also has a 'permission' column of value 'ro' or 'rw' to designate if that team has read-only or read-write access to the folder.

I changed my mapping as you suggested to:
Code:
@AccessType("field")
@Entity
@Table(name="C_Folder_TeamSecurity")
@SequenceGenerator(name="seq", sequenceName="C_Folder_TeamSecurity_Seq")
public class FolderTeamPermission
  implements TeamPermission<Folder>
{
  @Id
  @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq")
  private Integer id;
 
  @ManyToOne(cascade={CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
  @JoinColumn(name="folderId")
  private Folder folder;
 
  private String permission;
 
  @ManyToOne(cascade={CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
  @JoinColumn(name="teamName")
  private SecurityTeam team;


This still doesn't work, I am still only getting an update of folder, but never an insert of FolderTeamPermission. As I mentioned, I have not had this problem when using XML mapping, it seems to be a interesting behavior with annotations.

Please include solutions only using annotations not xml mapping.

Thank you,
Andrew


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 12:09 pm 
Beginner
Beginner

Joined: Wed Nov 30, 2005 10:25 pm
Posts: 25
If it makes any difference, the SecurityTeam doesn't reverse-map the folders/folder security (there is no collection in the security team for the folders)

Security team definition:

Code:
@AccessType("field")
@Entity
@Table(name="S_Teams", schema="spappset")
public class SecurityTeam
{
  @Id
  @Column(name="teamname")
  private String name;
 
  @Basic
  private String description;
 
  @Basic
  @Column(name="active_status")
  private String activeStatus;
 
  @ManyToMany(cascade=CascadeType.ALL, mappedBy="teams")
  private Set<CPMUserBean> users = new HashSet<CPMUserBean>();


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 1:09 pm 
Expert
Expert

Joined: Mon Jan 09, 2006 5:01 pm
Posts: 311
Location: Sacramento, CA
did you try to use the "inverse" attribute?

Here are some hopefully helpfull quotes from the doc (v3 reference.pdf)

page 15 & 16:
Quote:
The rules you have to remember
are straightforward: All bi-directional associations need one side as inverse. In a one-to-many association it has to be the many-side, in many-to-many association you can pick either side, there is no difference.


page 84:
Quote:
Changes made only to the inverse end of the association are not persisted. This means that Hibernate has two
representations in memory for every bidirectional association, one link from A to B and another link from B to
A. This is easier to understand if you think about the Java object model and how we create a many-to-many relationship
in Java:


page 185:
Quote:
Just before you ditch bags forever, there is a particular case in which bags (and also lists) are much more performant
than sets. For a collection with inverse="true" (the standard bidirectional one-to-many relationship
idiom, for example) we can add elements to a bag or list without needing to initialize (fetch) the bag elements!
This is because Collection.add() or Collection.addAll() must always return true for a bag or List (unlike
a Set). This can make the following common code much faster.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 1:22 pm 
Beginner
Beginner

Joined: Wed Nov 30, 2005 10:25 pm
Posts: 25
There is no such thing as inverse, this is a hibernate xml mapping construct and does not relate to annotated mapping.

My annotations are taken directly from the hibernate annotations documentation under the "2.2.5.3.2.1. Bidirectional" section:

http://www.hibernate.org/hib_docs/annot ... ollections

I am beginning to think there is a bug in the annotation configuration and its use with the SessionFactory/Session. Perhaps annotated configuration only works with EJB3 Entity Managers and not Sessions?

Can someone confirm this?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 1:46 pm 
Expert
Expert

Joined: Mon Jan 09, 2006 5:01 pm
Posts: 311
Location: Sacramento, CA
Sorry - as you can probably tell - I no nothing about annotations - however, by way of a last comment: it seems odd that the concepts would go away with Annotations that were in place for xml mappings...and if they didn't go away, then I'd find the place where/how they are configured in Annotations.

Good luck,
JT


Top
 Profile  
 
 Post subject: Okay this is bad
PostPosted: Wed Feb 22, 2006 1:49 pm 
Beginner
Beginner

Joined: Wed Nov 30, 2005 10:25 pm
Posts: 25
Okay, I am into WTF stage. I looked at the documentation, and there is another way to map bi-directional objects and tried it, and it is even worse!

I really don't get it, this is code directly from the hib. annotations documentation!

Folder:
Code:
@Entity
@AccessType("field")
@Table(name="C_Folder")
@SequenceGenerator(name="seq",sequenceName="C_Folder_Seq")
public class Folder
{
  private String path;
 
  //@OnDelete(action=OnDeleteAction.CASCADE)
  @OneToMany(cascade=CascadeType.ALL)
  @JoinColumn(name="folderId")
  private List<FolderTeamPermission> teamPermissions =
    new ArrayList<FolderTeamPermission>();
 
  @Id
@GeneratedValue(generator="seq",strategy=GenerationType.SEQUENCE)
  private Integer id;


Permission:
Code:
@AccessType("field")
@Entity
@Table(name="C_Folder_TeamSecurity")
@SequenceGenerator(name="seq", sequenceName="C_Folder_TeamSecurity_Seq")
public class FolderTeamPermission
  implements TeamPermission<Folder>
{
  @Id
  @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq")
  private Integer id;
 
  @ManyToOne//(cascade={CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
  @JoinColumn(name="folderId",insertable=false,updatable=false)
  private Folder folder;
 
  private String permission;
 
  @ManyToOne
  @JoinColumn(name="teamName",insertable=true,updatable=true)
  private SecurityTeam team;


Error:
Code:
Caused by: java.sql.SQLException: ORA-01400: cannot insert NULL into ("SPADMIN"."C_FOLDER_TEAMSECURITY"."FOLDERID")


I double and triple checked that I am setting the folder on the m2m object.

BTW - the folder and m2m tables are in the "SPADMIN" schema and the team is in the "SPAPPSET" schema.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 1:54 pm 
Beginner
Beginner

Joined: Wed Nov 30, 2005 10:25 pm
Posts: 25
Sorry I am seeming harse, I just getting royally mad/frustrated here.

The 'mappedBy="folder"' is supposed to be the equivalent of 'inverse="true"', but it doesn't seem to be working.

I either think bi-directional mapping doen't work in hibernation annotations 3.1b8 (which would be a shock to me) or the documentation is wrong.

Isn't there someone on the hibernate-annotations team with a clue?

I'm about to give up on hibernate-annotations (although it scares me for my other project that I am using EJB3/EntityManager+Seam for)

Very desperate,
Andrew


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 2:24 pm 
Expert
Expert

Joined: Mon Jan 09, 2006 5:01 pm
Posts: 311
Location: Sacramento, CA
whenever I get in a situation like this - I revert to very simple code constructs, and attempt to prove the concepts with these "working" basic building blocks - perhaps try and reproduce the "examples" and/or by using code from the test or eg directory.

-JT


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 2:46 pm 
Beginner
Beginner

Joined: Wed Nov 30, 2005 10:25 pm
Posts: 25
There are no examples, but when I look at their test code, they are persisting the child manually. There is no test code or example code that adds a child to an existing parent (only a new parent, which does work for me)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 3:25 pm 
Beginner
Beginner

Joined: Wed Nov 30, 2005 10:25 pm
Posts: 25
Finally found it. Went into debug mode and found out that my collection was empty even though it had 2. Some @!#&%(*@!#& code was basically clearing the collection in an entirely different method.

Man that really sucks. Sorry for getting you invovled in a dumb user bug


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 3:36 pm 
Expert
Expert

Joined: Mon Jan 09, 2006 5:01 pm
Posts: 311
Location: Sacramento, CA
doing a google (on "@ManyToOne" +hibernate) I came up with:

some bug on @ManyToOne (may be related)
http://opensource2.atlassian.com/projec ... wse/ANN-15
http://opensource2.atlassian.com/projec ... wse/ANN-16

and an article talking about annotations (in German) but code examples are there:

http://www.doag.org/pub/docs/sig/develo ... rnate3.pdf

didn't verify any of this though.. hope it helps.

-JT

_________________
-JT

If you find my replies helpful, please rate by clicking 'Y' on them. I appreciate it.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 13 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.