Can Add Extra Field(S) to @Manytomany Hibernate Extra Table

Can add extra field(s) to @ManyToMany Hibernate extra table?

If you add extra fields on a linked table (STUDENT_COURSE), you have to choose an approach according to skaffman's answer or another as shown bellow.

There is an approach where the linked table (STUDENT_COURSE) behaves like a @Embeddable according to:

@Embeddable
public class JoinedStudentCourse {

// Lets suppose you have added this field
@Column(updatable=false)
private Date joinedDate;

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="STUDENT_ID", insertable=false, updatable=false)
private Student student;

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="COURSE_ID", insertable=false, updatable=false)
private Course course;

// getter's and setter's

public boolean equals(Object instance) {
if(instance == null)
return false;

if(!(instance instanceof JoinedStudentCourse))
return false;

JoinedStudentCourse other = (JoinedStudentCourse) instance;
if(!(student.getId().equals(other.getStudent().getId()))
return false;

if(!(course.getId().equals(other.getCourse().getId()))
return false;

// ATT: use immutable fields like joinedDate in equals() implementation
if(!(joinedDate.equals(other.getJoinedDate()))
return false;

return true;
}

public int hashcode() {
// hashcode implementation
}

}

So you will have in both Student and Course classes

public class Student {

@CollectionOfElements
@JoinTable(
table=@Table(name="STUDENT_COURSE"),
joinColumns=@JoinColumn(name="STUDENT_ID")
)
private Set<JoinedStudentCourse> joined = new HashSet<JoinedStudentCourse>();

}

public class Course {

@CollectionOfElements
@JoinTable(
table=@Table(name="STUDENT_COURSE"),
joinColumns=@JoinColumn(name="COURSE_ID")
)
private Set<JoinedStudentCourse> joined = new HashSet<JoinedStudentCourse>();

}

remember: @Embeddable class has its lifecycle bound to the owning entity class (Both Student and Course), so take care of it.

advice: Hibernate team suppports these two approachs (@OneToMany (skaffman's answer) or @CollectionsOfElements) due some limitations in @ManyToMany mapping - cascade operation.

regards,

Spring hibernate ManyToMany with extra fields

As long as you are creating the schema yourself, you don't need to add the fields to the join table. Just add them to your license Entity. This would be an approximation of what you seem to be trying to do.

@Entity
public class Driver {
@Id @GeneratedValue private Integer id;
@OneToMany private List<License> licenses;
... Driver Name, Number, & DateOfBirth ...
}

and

@Entity
public class License {
@Id @GeneratedValue private Integer id;
private String licenseName;
// add your fields here.
@Temporal(TemporalType.DATE)
private Date expirationDate;
private String issueState;
}

Again, you don't want to mess with the join table, they are typically created automatically by the persistence provider.

The licenses list in the Driver table will refer to a join table that will hold many licenses for one driver, hence the OneToMany relation.

EDIT: If you have a specific license and want to find out which driver it belongs to, say because you have looked it up by its name, then you should add a reference back to the driver:

@ManyToOne
private Driver driver;

It will be a ManyToOne because you will have Many licenses which refer to One driver. This relationship will use the same Join Table that the licenses list in Driver uses. This will also create a circular reference, Driver refers to License and License refers to Driver. You will have to create the Licenses first, save them, create the Driver, add the licenses, save it, then merge the Driver into the License.

    for(License license: licenses) {
em.persist(license);
}
Driver driver = new Driver();
driver.getLicenses().add(licenses);
em.persist(driver);
// merge circular dependency
for(License license: licenses) {
license.setDriver(driver);
em.merge(license);
}

GOOD ADVICE: You should turn on the SQL output and play with the application a little bit to get a feel for what it can do and how it does it. Seeing everything in action will help you get a better feel about how this works. I usually make a simple web page with buttons such as create, print, delete and the like and watch the debug output.

Hibernate and Jackson manyToMany relation with extra fields

Finally, I solved my problem. Instead of using a composite key, I changed my database model to use a primary id key and 2 references to my concerned tables. Mapping is easier and I get my information.

Hibernate 4 - Can add extra field(s) to @ManyToMany Hibernate extra table?

Hibernate 4 only supports the standard JPA annotation, which is @ElementCollection.

Note that even Hibernate 3 recommends using this standard annotation:

Deprecated. use @ElementCollection

Hibernate Many to Many Mapping with Additional Column?

Relationships do not have persistent attributes to set, only entities do have. That's why you need third entity between. It will have two @Id attributes and consequently @IdClass is needed, because identity is derived from Group and User:

@Entity
public class User {
@Id int id;
@OneToMany(mappedBy = "user")
private Set<GroupMemberShip> groupMemberShips;
...
}

@Entity
public class Group {
@Id int id;
@OneToMany(mappedBy = "group")
private Set<GroupMemberShip> groupMemberShips;
...
}

@Entity
@IdClass(GroupMemberShipId.class)
public class GroupMemberShip {
@Id @ManyToOne User user;

@Id @ManyToOne Group group;

private boolean isThisUserIsGroupManager;
...
}

public class GroupMemberShipId implements Serializable {
int user;
int group;
...
}

Hibernate @ManyToMany with extra columns

Because you are using @IdClass you don't need to annotate PatientDiseaseId with @Embedded and @Column. And you have to refer to the entities.

This is what it should look like:

public class PatientDiseaseId implements Serializable {

private static final long serialVersionUID = 1L;

private Patient patient;

private Disease disease;

//getters and setters
//hashCode and equals
}

Mapping many-to-many association table with extra column(s)

Since the SERVICE_USER table is not a pure join table, but has additional functional fields (blocked), you must map it as an entity, and decompose the many to many association between User and Service into two OneToMany associations : One User has many UserServices, and one Service has many UserServices.

You haven't shown us the most important part : the mapping and initialization of the relationships between your entities (i.e. the part you have problems with). So I'll show you how it should look like.

If you make the relationships bidirectional, you should thus have

class User {
@OneToMany(mappedBy = "user")
private Set<UserService> userServices = new HashSet<UserService>();
}

class UserService {
@ManyToOne
@JoinColumn(name = "user_id")
private User user;

@ManyToOne
@JoinColumn(name = "service_code")
private Service service;

@Column(name = "blocked")
private boolean blocked;
}

class Service {
@OneToMany(mappedBy = "service")
private Set<UserService> userServices = new HashSet<UserService>();
}

If you don't put any cascade on your relationships, then you must persist/save all the entities. Although only the owning side of the relationship (here, the UserService side) must be initialized, it's also a good practice to make sure both sides are in coherence.

User user = new User();
Service service = new Service();
UserService userService = new UserService();

user.addUserService(userService);
userService.setUser(user);

service.addUserService(userService);
userService.setService(service);

session.save(user);
session.save(service);
session.save(userService);


Related Topics



Leave a reply



Submit