-->
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.  [ 2 posts ] 
Author Message
 Post subject: Using @ManyToMany without update()
PostPosted: Mon Apr 21, 2008 4:05 pm 
Newbie

Joined: Mon Apr 21, 2008 3:27 pm
Posts: 5
Hibernate version: 3.2.6.ga
Hibernate annotations version: 3.2.1.ga

Hello, i'm doing a migration from xml mappings to hibernate annotation mappings in my application, and then i want to use hibernate search; but i still have a really problem in the transition from xml mappings to hibernate annotations.

At first, i will explain my model, that is a little complex.

I have "users" and "items" tables, and there is a "many-to-many" relation between these entities, and we have a "users_items" relation table. Also, "users_items" represents the item for this especific user, and have the information of creation_date (the date that the item was added to the user), and other stuff.

In the model of objects i have:

User, that contains many UserItem.
UserItem have an UserItemId that have an User and an Item.
UserItem have the creation date and other stuff.
Item have got a set of Users.

Doing this in xml mapping is like that:

User
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
  <class name="com.xxx.User" table="users">
    <id name="id" column="id" type="java.lang.Long">
      <generator class="native"/>
    </id>

    <set name="userItems" table="users_items" cascade="all">
      <key column="user_id"/>
      <one-to-many class="com.xxx.UserItem"/>
    </set>

  </class>
</hibernate-mapping>


UserItem
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
  <class name="com.xxx.UserItem" table="users_items" abstract="true">
   <composite-id name="id" class="com.xxx.UserItemId">
       <key-many-to-one name="item" column="item_id" class="com.xxx.Item"/>
       <key-many-to-one name="user" column="user_id" class="com.xxx.User"/>
    </composite-id>

    <property name="creationDate" column="creation_date" type="java.util.Date" not-null="true" />

  </class>
</hibernate-mapping>


Item
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

  <class name="com.xxx.Item" table="items" abstract="true">
    <id name="id" column="id" type="java.lang.Long">
      <generator class="native"/>
    </id>

    <set name="users" table="users_items" inverse="true">
        <key column="item_id"/>
        <many-to-many column="user_id" class="com.xxx.User" />
    </set>

  </class>
</hibernate-mapping>


And this mappins works very good for me, life is good! :D

But when i use Annotations i have a problem with the "users" set inside the item. I dont want that collection updates the database.

Im using the following annotations:

User
Code:
@Entity
@Table(name="users")
public class User {

    private Long id;
    private Collection<UserItem> userItems;

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }

    @OneToMany(cascade=CascadeType.ALL)
    @JoinColumn(name="user_id")
    public Collection<UserItem> getUserItems() {
        return userItems;
    }
    public void setUserItems(Collection<UserItem> userItems) {
        this.userItems = userItems;
    }
}


UserItem & UserItemId
Code:
@Entity
@Table(name="users_items")
public class UserItem {

    private UserItemId id;
    private Date creationDate;

    @EmbeddedId
    public UserItemId getId() {
        return id;
    }
    public void setId(UserItemId id) {
        this.id = id;
    }

    @Column(name="creation_date", nullable=false)
   public Date getCreationDate() {
        return creationDate;
    }
    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }
}


@Embeddable
public class UserItemId implements Serializable{

    private User user;
    private Item item;

    @ManyToOne
    @JoinColumn(name="user_id")
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }

    @ManyToOne
    @JoinColumn(name="item_id")
    public Item getItem() {
        return item;
    }
    public void setItem(Item item) {
        this.item = item;
    }
}


Item, and here is the problem
Code:
@Entity
@Table(name="items")
public abstract class Item {

    private Long id;
    private Set<User> users;

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }

    @ManyToMany(
        targetEntity=User.class
    )
    @JoinTable(
        name="users_items",
        joinColumns=@JoinColumn(name="user_id", insertable=false, updatable=false),
        inverseJoinColumns=@JoinColumn(name="item_id")
    )
    public Set<User> getUsers() {
        return users;
    }
    public void setUsers(Set<User> users) {
        this.users = users;
    }   
}

When i use this code, i have the following problem:

Code:
org.springframework.jdbc.UncategorizedSQLException: Hibernate flushing: Could not execute JDBC batch update; uncategorized SQLException for SQL [insert into users_items (user_id, item_id) values (?, ?)]; SQL state [S1000]; error code [1364]; General error,  message from server: "Field 'creation_date' doesn't have a default value"; nested exception is java.sql.BatchUpdateException: General error,  message from server: "Field 'creation_date' doesn't have a default value"
Caused by:
java.sql.BatchUpdateException: General error,  message from server: "Field 'creation_date' doesn't have a default value"
   at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1404) ... ... ...


Ok, fine. I undertand. The @ManyToMany in the Item class is trying to insert the new associations, and fails.
In xml mappings with the "inverse=true" this mapping dont try to insert the new associations. But, how can i do this in annotations!?

I cant use something like that:
Code:
@ManyToMany(
    mappedBy = "items",
    targetEntity = User.class
)

Because there is no "inverse" mapping really. There is other complex mapping that does the "many-to-many" for the Item also.

Any idea for this?

Thanks Anyway.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 24, 2008 3:09 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Unfortunately I don't think it's possible to support that asymmetric model in annotations.
You will have to map userItem (which is not really what you want).

_________________
Emmanuel


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 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.