I tried to create an unidirectional OneToMany relation with a JoinTable in Play Framework 2.1. However, the framework is not generating the 'JoinTable': "transformation_input_files". The strange part is that if I change the relation to ManyToMany the table is generated. Here is the code:
So its about an Transformation class containing multiple S3Files. Here is the Transformation file:
#Entity
#Table(name = "transformations")
public class Transformation extends Model {
#Id
public Long id;
/*...*/
#OneToMany(cascade = CascadeType.PERSIST)
#JoinTable(
name="transformation_input_files",
joinColumns = #JoinColumn( name="transformation_id"),
inverseJoinColumns = #JoinColumn( name="input_file_id")
)
public List<S3File> inputFiles;
}
Here is the S3File:
#Entity
#Table(name="s3files")
public class S3File extends Model {
#Id
public Long id;
/*...*/
}
The S3Files are used in more models, so that can not be a bidirectional relation. If I change #OneToMany in #ManyToMany it does generate the join table, however, I do like to stick with the #OneToMany relation.
How do I solve this problem? Did I missed something?
In one-to-many relationship you have to store the relation in "Many" entity..if you don't want to store the value in the S3File class you have to create another class to join the two classes.
Example:
#Entity
#Table(name="transformations_ s3files")
public class Relation extends Model {
#Id
public Long id;
#ManyToOne
public Transformation transformation;
#OneToOne
public S3File file;
}
Related
I have a project that uses Hibernate and is divided into multiple modules.
I have the following modules:
device (defines entity Device)
appstore (defines entity Application)
device-appstore-integration (adds many-to-many relationship between Device and Application).
Entities look like this:
#Entity
#Table(name = "devices")
public class Device extends AbstractAuditingEntity implements Serializable
{
#NotNull
#EmbeddedId
private DeviceIdentity identity;
// ...
}
#Entity
#Table(name = "apps")
public class App extends AbstractAuditingEntity implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// ...
}
Now I want device-appstore-integration module to add many-to-many relationship between the two entities above.
I thought about adding entity DeviceWithInstalledApps to define this many2many relationship and used the following code:
#Entity
#Table(name = "devices")
public class DeviceWithInstalledApps extends Device
{
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(
name = "devices_installed_apps",
joinColumns = {/*...*/},
inverseJoinColumns = {/*...*/}
)
private Set<App> installedApps = new HashSet<>();
// ...
}
The problem is that Hibernate requires devices table to include dtype column and treats DeviceWithInstalledApps as a separate entity that inherits from Device but I don't actually want it to be a separate entity. It's still the same entity, just with many-to-many relationship added so that I can actually access this relationship, no columns are added so there is no actual need to provide dtype column, it simply doesn't make sense in this context.
Is there any other way to define many-to-many relationship in JPA/Hibernate so that I can actually implement business logic without getting into issues mentioned above?
I'm starting my first project with Hibernate 4.2.21 and first with JPA 2.0, I want to create a relationship OneToMany Unidirectional. I saw a lot examples in version of Hibernate 3 but not much in 4.2.21 This example works perfectly but I don't know if is a good practice, I want to know the Opinion from another members about that?
Relationship One To Many:
-Parent Template:
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "template_id")
private Set<Variable> variables = new LinkedHashSet<Variable>();
-Child: Variable
#Column(name = "template_id", nullable = false)
Integer templateId;
According with this another post's.
Hibernate unidirectional one to many association - why is a join table better?
http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-mapping-association-collections
A unidirectional one to many using a foreign key column in the owned entity is not that common and not really recommended. We strongly advise you to use a join table for this kind of association (as explained in the next section). This kind of association is described through a #JoinColumn
#Entity
public class Customer implements Serializable {
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
#JoinColumn(name="CUST_ID")
public Set<Ticket> getTickets() {
...
}
#Entity
public class Ticket implements Serializable {
... //no bidir
}
Unidirectional with join table
A unidirectional one to many with join table is much preferred. This association is described through an #JoinTable.
#Entity
public class Trainer {
#OneToMany
#JoinTable(
name="TrainedMonkeys",
joinColumns = #JoinColumn( name="trainer_id"),
inverseJoinColumns = #JoinColumn( name="monkey_id")
)
public Set<Monkey> getTrainedMonkeys() {
...
}
#Entity
public class Monkey {
... //no bidir
}
Finally the only way it's implement the bidirectional method... yes or no?
I have the following entities:
Project: id:int, name:String, workers:Set
Worker: id:int, name:String, projects:Set
Project_Worker: id:int,
project_id:int, worker_id:int
So, I have my own table to 'solve' the many to many relation. <-- ya I need it - can't use just many to many and let JPA create the table cause I need the extra entity.
Now I tried a lot. Just so that JPA wont create an own table and extra columns and so on, but it wont work. My code so far:
#Entity
#Table("Worker")
public class Worker implements Serializable {
...
#ManyToMany
#JoinTable(name = "Project_Worker",
joinColumns = {#JoinColumn(name = "Worker_id", referencedColumnName="id")},
inverseJoinColumns = {#JoinColumn(name = "project_id", referencedColumnName="id")})
private Set<Project> projects;
The Project entity looks the same. just with the changed join columns.
My table: Project_Worker columns have at the moment no annotations cause if I use for example:
#JoinTable(name="Project",
joinColumns = {#JoinColumn(name = "id")})
JPA creates in the worker and project table an extra column instead in the Project_Worker table..
So I just want to map the many-to-many relation over my own table with my own attributes.
I also tried the solution - which worked - that just the project_worker table will have OneToMany annotations, but so the project and worker entity won't be able to use the Set and i have to look every time in the project_worker table for the right row...
If you want to map it as a many-to-many Project<->Worker via your join table you will need to ditch the id column in the project_worker table and it should work as you expect.
If you can't do this then you will need ProjectWorker as an entity in code then the relationship should be a one-to-many from Worker and Project to ProjectWorker.
#Entity
#Table("Worker")
public class Worker implements Serializable {
...
#OneToMany(mappedBy = "worker")
private Set<ProjectWorker> projectWorker;
#Entity
#Table("Project")
public class Project implements Serializable {
...
#OneToMany(mappedBy = "project")
private Set<ProjectWorker> projectWorker;
#Entity
#Table("ProjectWorker")
public class ProjectWorker implements Serializable {
...
#ManyToOne
#JoinColumn(name = "worker_id")
private Worker worker;
#ManyToOne
#JoinColumn(name = "project_id")
private Project project;
Let's say I have a parent table A and a child table B, they have a foreign key linking A.id and B.id, the problem is this parent table and the FK have been created recently and there are too many places which persisting a child table, so I'm waiting for a simple way to persist the parent table and link it to the child table. Is it possible to handle this task by using Hibernate instruments? I was trying to use cascades but no success, looks they only work if we persist a parent entity.
So the structure is the following:
#Entity
class A {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "a_id")
long id;
}
#Entity
class B {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "b_id")
long id; // FK to a_id
}
class BDao {
void store(B b) {
session.save(b); // to many places
}
}
Will appriciate any help, thanks!
Yeah! I've fixed it, just in case somebody wants to know the answer I'm leaving my solution here. Perhaps you guys will spent less time than me solving the same problem.
So first you need to use #Inheritance(strategy= InheritanceType.JOINED) annotation to describe the parent entity:
#Entity
#Inheritance(strategy= InheritanceType.JOINED)
#PrimaryKeyJoinColumn(name = "a_id")
public class A {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "a_id")
protected Integer id;
}
Then describe the child entity like
#Entity
#AssociationOverride(name="a_id", joinColumns = #JoinColumn(name="b_id"))
#PrimaryKeyJoinColumn(name = "b_id")
public class B extends A {
...
}
I've left here #AssociationOverride because in my case I have different primary key name so perhaps it helps somebody as well.
That's it! Now when you persist a child entity it will create two rows - one for a parent and one for a child tables.
I am trying to get the following type of mapping to work
Table event has the following columns:
id (PK)
prodgroup
errandtype
table errandtype : errandtype
table prodgroup: prodgroup
I have corresponding JPA classes
#Entity
#Table(name="event")
public class MyEvent {
#Id
int id;
// what mapping should go here?
Prodgroup prodgroup;
// what mapping should go here?
ErrandType errandtype;
}
#Entity
public class Prodgroup {
#Id
private String prodgroup;
}
#Entity
public class ErrandType {
#Id
private String errandtype;
}
Ok so questions are marked as comments in the code but I'll try to be explicit anyway.
In the above example I want my Prodgroup and ErrandType fields in the MyEvent class to be set to corresponding Prodgroup and Errandtype instances
I have tried #OneToOne relationships with #joincolumns and with mappedby attribute, but I just can't get it working and I've lost all sense of logical approach. My grasp of JPA entity mapping is clearly weak.
So can anyone bring some clarity?
It should be:
#Entity
#Table(name="event")
public class MyEvent {
#Id
int id;
// what mapping should go here?
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "prodgroup_id", insertable = true, updatable = true)
Prodgroup prodgroup;
// what mapping should go here?
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "errandtype_id", insertable = true, updatable = true)
ErrandType errandtype;
}
#Entity
public class Prodgroup {
#Id
private String prodgroup;
}
#Entity
public class ErrandType {
#Id
private String errandtype;
}
FetchType Eager means the object will be always loaded (would be "Lazy" by default if not specified).
CascadeType.ALL means mearge/persist/remove will be also done to linked tables.
Sebastian
Your table columns event.prodgroup and event.errandtype are foreign keys to respective tables (prodgroup, errandtype). So you need #ManyToOne association (because many events may share one prodgroup or errantype).