1

I wanted to create bidirectional one to one relationship with shared primary key.

As it is stated here JPA Hibernate One-to-One relationship I have:

@Entity
public class UserProfileInformation {

    @Id
    @GeneratedValue(generator = "customForeignGenerator")
    @org.hibernate.annotations.GenericGenerator(
        name = "customForeignGenerator",
        strategy = "foreign",
        parameters = @Parameter(name = "property", value = "userEntity")
    )
    long id;

    private long itemsPerPage;

    @OneToOne(mappedBy="userProfileInformation")
    private UserEntity userEntity;
...}

@Entity
@Table(name = "UserTable")
public class UserEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String publicName;

    private String password;

    private String emailAddress;

    private String name; 

    private boolean active;

    @OneToOne(cascade=CascadeType.ALL)
    @PrimaryKeyJoinColumn
    private UserProfileInformation userProfileInformation;
...}

now, when I try to persist my user in the database, I am getting org.hibernate.id.IdentifierGenerationException: null id generated for:class pl.meble.taboret.model.UserProfileInformation. Is it because, when userProfileInformation is persisted to the database userEntity doesn't have id generated at that point?

Also, what can I do to create bidirectional relationship with shared primary key in my example?

EDIT: Requested code, this is simple controller to test the operation of persisting UserEntity.

@Controller
@RequestMapping("/test")
public class TestController {
    @Autowired
    UserDao userDao;

    @RequestMapping(method= RequestMethod.GET)
    public String t(Model model){
        UserEntity entity=new UserEntity();
        entity.setActive(false);
        entity.setEmailAddress("a");
        entity.setName("name");
        entity.setPassword("qqq");
        entity.setPublicName("p");
        UserProfileInformation p = new UserProfileInformation(entity);
        entity.setUserProfileInformation(p);
        userDao.addUser(entity);
        return "login";
    }
}
Community
  • 1
  • 1
Andna
  • 6,539
  • 13
  • 71
  • 120
  • Show the code where you are creating/saving the UserProfileInformation entity. Are you setting the userEntity reference correctly? Also check if changing the type from long to Long works. – gkamal Sep 09 '12 at 13:15
  • I added the code to the edited first post, also, changing type from long to Long didn't solve the issue. – Andna Sep 09 '12 at 14:43
  • check this out - http://stackoverflow.com/questions/4027623/how-do-i-properly-cascade-save-a-one-to-one-bidirectional-relationship-on-prima. I think it something to do with which side is the owning side - you probably need to swap the mappedBy & PrimaryKeyJoinColumn – gkamal Sep 09 '12 at 16:42
  • I read this post, but the thing is, mapped by is pointing to mark the non-owning side of association. It is strange to me that I should use mapped by on the UserEntity side, which is the owning side imo. I just can't wrap my head around this so to speak. – Andna Sep 09 '12 at 16:59

1 Answers1

1

I think the problem is with the id generation strategy. For hibernate @GeneratedValue(strategy = GenerationType.AUTO) translates into a native identifier generation. This means that hibernate expects an identity id field for the UserTable.

I don't know exactly how SQLite works in terms of identity columns, but it seems from this SO question is a little different (see the second answer).

Anyway if you plan to run your application on multiple databases is better for portability to change the id generation strategy from GenerationType.AUTO and use hibernate enhanced generators: SequenceStyleGenerator or TableGenerator. See this link in the hibernate documentation.

EDIT:

I tried to reproduce your problem, and it seems that SQLite dialect is not among the officially supported hibernate dialects. Meanwhile I tested your case with the H2 embeded database and it works as expected: your mappings are correct.

If you are using an unofficial SQLite dialect it might be a bug with this dialect.

Community
  • 1
  • 1
dcernahoschi
  • 14,968
  • 5
  • 37
  • 59
  • I don't know if this is a problem strictly with id generation. Before I didn't have UserProfileInformation class, and I could persist UserEntity with no problems. – Andna Sep 09 '12 at 17:02
  • if you enable hibernate sql logs what sqls do you see when persisting the user entity? Just before the exception. – dcernahoschi Sep 09 '12 at 17:16
  • I have sql logs enabled, there is no sql visible. The exception is `null id generated for:class pl.meble.taboret.model.UserProfileInformation`, and because I am saving UserEntity and I have Cascade on all, Hiberante wants to store UserProfileInformation first, but he can't, because there is no id in the corresponding UserEntity. When I remove the `@GeneratedValue` from both of the classes, and manually set the id in UserEntity, everything is persisting ok. – Andna Sep 09 '12 at 17:35
  • Also, as I said in my previous comment, if I manually set Id of UserEntity I am getting this sql log `Hibernate: /* insert pl.meble.taboret.model.UserProfileInformation */ insert into UserProfileInformation (itemsPerPage, id) values (?, ?) Hibernate: /* insert pl.meble.taboret.model.UserEntity */ insert into UserTable (active, emailAddress, name, password, publicName, id) values (?, ?, ?, ?, ?, ?) ` so we see here that UserProfileInformation is stored first. – Andna Sep 09 '12 at 17:41
  • what hibernate and SQLite version? I'll set up small project to test your use case. – dcernahoschi Sep 09 '12 at 18:27
  • Hibernate - 3.6.0. SQLite - 3.7.2 – Andna Sep 09 '12 at 18:42
  • Yes, I am using SQL dialect found somewhere on the net. Thanks then, for clearing it up. I was mighty confused why the solutions that were provided everywhere didn't seem to work for me. I wasn't suspecting sql dialect though. – Andna Sep 11 '12 at 07:57