I've been bashing my head on my keyboard for two days trying to figure this out...
Some background: We have a data model set up with a Perl code base that runs straight native SQL statements to the database via ODBC. For certain reasons, we decided to rewrite the code in Java... I thought it would be a good idea to use Hibernate to define all of the mappings. We don't want to edit the data model.
For simplicity sake, I can express the problem with only part of our data model. We have the entities "Job","JobDatabase" and "JobTable".
Job has a PK of job_name. Database has a PK of job_name,name. Table has a PK of job_name,src_database_name,name. As you may expect, Job has a OneToMany relationship with JobDatabase, and Database has a OneToMany with JobTable.
For purposes of this test, I'm starting with empty tables and trying to create some sample data. I can insert a Job and a JobDatabase, but when I try to insert the JobTable, Hibernate throws an error. Or more accurately, that is where it complains. It doesn't start executing my code because it detects the mapping error. However, if I remove the association between JobDatabase and JobTable, it will insert all Job and JobDatabase records correctly with no errors.
Sample Classes (all fields have getters/setters... there are also many other fields):
#Entity
#Table(name="Job")
public class Job implements Serializable {
#Id
#Column(name="job_name",nullable = false)
private String jobName;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "job_name", referencedColumnName = "job_name")
private Set<JobDatabase> databases;
}
#Entity
#Table(name="JobDatabase")
public class JobDatabase implements Serializable {
#Id
#Column(name="job_name",nullable = false)
private String jobName;
#Id
#Column(name="name",nullable = false)
private String name;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumns({
#JoinColumn(name = "job_name", referencedColumnName = "job_name"),
#JoinColumn(name = "name", referencedColumnName = "src_database_name")
})
private Set<JobTable> tables;
}
#Entity
#Table(name="JobTable")
public class JobTable implements Serializable{
#Id
#Column(name="job_name",nullable = false)
private String jobName;
#Id
#Column(name="src_database_name",nullable = false)
private String srcDatabaseName;
#Id
#Column(name="name",nullable = false)
private String name;
}
The error:
Exception in thread "main" org.hibernate.MappingException: Unable to find column with logical name: src_database_name in JobDatabase
I keep getting this error. I do not understand why it is looking for the referenced column in the entity "owning" the mapping. src_database_name does indeed only exist in JobTable - it is referred to as "name" in JobDatabase. JobTable also has a "name" field, but it refers to the name of the Table.
You need to have src_database_name column in your JobDatabase table. Or you can change src_database_name to other column name.
For composite key reference column must be present in your source table.
Related
I have two entities mapped to one another using the oneToMany annotation. One entity is bookedBus and the second is drivers The drivers entity would already have a row inserted into that would later become a foreign reference (FK) to bookedBus entity(PK). Below are the two entities, setters and getter have been skipped for brevity.
First entity
#Entity
#Table(name = "bookedBuses")
public class BookedBuses implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "driver_id")
private Drivers driver;
}
Second entity
#Entity
public class Drivers implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "driver")
private List<BookedBuses> bookedBus;
}
Now When I try to save to the booked bus entity it throws the following exception
org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.bus.api.entity.Drivers; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.bus.api.entity.Drivers
Below is how I tried saving to the bookedBus entity
BookedBuses bookedRecord = new BookedBuses();
bookedRecord.setBookedSeats(1);
bookedRecord.setBookedBusState(BookedBusState.LOADING);
bookedRecord.setBus(busService.getBusByPlateNumber(booking.getPlateNumber()));
bookedRecord.setRoute(booking.getRoute());
infoLogger.info("GETTING DRIVER ID ======= " + booking.getDriver().getId());
Drivers drivers = new Drivers(booking.getDriver().getId());
List<BookedBuses> d_bu = new ArrayList<>();
drivers.setBooked(d_bu);
drivers.addBooked(bookedRecord);
bookedRecord.setDriver(drivers);
bookedBusService.save(bookedRecord);
My BookBusService Save Method as requested
#Autowired
private BookedBusRepository bookedBusRepo;
public boolean save(BookedBuses bookedRecord) {
try {
bookedBusRepo.save(bookedRecord);
return true;
} catch (DataIntegrityViolationException ex) {
System.out.println(ex);
AppConfig.LOGGER.error(ex);
return false;
// Log error message
}
}
1st you have some mix up in naming: you have Driver & Drivers. Like this:
private Drivers driver;
Also selecting variable names like this:
BookedBuses bookedRecord = new BookedBuses();
will cause a lot of confusion. Do not mix plural & singular between types and preferably also do not introduce names that might not be easily associated like record. Also this:
private List<BookedBuses> bookedBus;
which should rather be like:
private List<BookedBus> bookedBuses;
(and would alsoi require change to your class name BookedBuses -> BookedBus)
Anyway the actual problem seems to lie here:
Drivers drivers = new Drivers(booking.getDriver().getId());
You need to fetch existing entity by id with a help of repository instead of creating a new one with id of existing. So something like:
Drivers drivers = driverRepo.findOne(booking.getDriver().getId()); // or findById(..)
It seems that you have a constructor (that you did not show) that enables to create a driver with id. That is not managed it is considered as detached. (You also have drivers.addBooked(bookedRecord); which you did not share but maybe it is trivial)
Note also some posts suggest to changeCascadeType.ALL to CascadeType.MERGE whether that works depends on your needs. Spring data is able to do some merging on save(..) based on entity id but not necessarily in this case.
This line
Drivers drivers = new Drivers(booking.getDriver().getId());
If you already have the driver ID available with you then there's no need to pull the driver ID again from the DB.
After removing the Cascade attribute from #OneToMany & #ManyToOne your code should work.
#Entity
#Table(name = "bookedBuses")
public class BookedBuses implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
`
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "driver_id")
private Drivers driver;
}
#Entity
public class Drivers implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name = "driver_id")
private List<BookedBuses> bookedBus;
}
I am trying to join to Hibernate Entities in a OneToOne Mapping. I am able to fetch the data for a given primary key from the Main Entity, the joining entity, however, returns null. I am new to hibernate and any help will be appreciated.
I have two Tables,
PT_CORE
Primary Key: ptId - Integer;
Foreign Key: stId(ST_AUX) - Integer;
Columns: ptId, ptName
ST_AUX
Primary Key: stId;
Columns: stId, stName
The two tables get populated by other applications and mine is a read-only operation.
Below is my first Entity class(PtCore.java)
#Entity
#Table(name="PT_CORE")
public class PtCore implements Serializable{
#Id
#Column(name="ptId", nullable = false)
private int id;
#Column(nullable=false)
private int stId; //The Foreign key column
#OneToOne
#JoinTable( name = "core_aux", joinColumns = {#JoinColumn(Name="ptId")},
inverseJoinColumns = {#JoinColumn(Name="stId")}
)
private StAux staux;
//Getters, setters and toString() for above
}
StAux is another Entity, defined as below,
#Entity
#Table(name="ST_AUX")
public class StAux implements Serializable {
#Id
#Column(nullable=false)
private Integer stId;
#OneToOne
private PtCore ptcore;
#Column
private String stName;
//Getters, Setters and toString follow.
}
I do below in the Service method:
PtCore obj = (PtCore) session.get(PtCore.class,1);
System.out.println(obj);
In the Results, I get the value of ptName, but the stAux class variables are null, Indicating that the join does not work as expected.
First of all you have the mapping information existing in your PT_CORE. And I assume it is something like FOREIGN KEY (stid) REFERENCES (stid). If you want to use existing schema and existing data I guess there is no mapping table core_aux really existing. At least you did not mention it. However it is visible as #JoinTable annotation but still there is this above mentioned foreign key which seems to be the real mapping (so again not the join table).
I suggest the following
remove this
#Column(nullable=false)
private int stId; //The Foreign key column
from your PtCore. I think it is not needed. Also in PtCore, remove the #JoinTable (because what I told above) and add mapping informaiion to #OneToOne annotation, like:
#OneToOne
#JoinColumn(name = "stid")
private StAux staux;
from your PT_CORE.
Then in StAux alter also a bit:
#Id
#Column(name = "stid") // this might not be needed but if there is like "st_id"...
private Integer stId; // so just for sure
#OneToOne(mappedBy = "staux")
private PtCore ptcore;
Because you have existing tables and constraints there might raise errors if hibernate tries to auto-generate those again by JPA instructions.
Check this for example for more information.
UPDATE: just realized also that in your title is #OneToMany but in your code is #OneToOne.
So you might want to elaborate your question and/or title a bit.
In your relation, the owning side is PtCore, the inverse side is StAux.
In bidirectional OneToOne relations, the inverse side has to have the mappedBy attribute. Actually, the mappedBy attribute contains the name of the association-field on the owning side.
So, you must change your inverse side code (StAux Entity). You have to add mappedBy attribute to #OneToOne in StAux class:
#OneToOne(mappedBy="staux")
private PtCore ptcore;
I have been using Hibernate a lot but using Hibernate/JPA with UUID got me stumped a bit. I am using hibernate 5.2.12.Final.
I have an object called TimePeriod with this mapping:
#Entity(name = "time_period")
public class TimePeriod extends AbstractDomainObject {
#OneToMany(mappedBy = "timePeriod", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<TimePeriodBlock> timePeriodBlocks = new ArrayList<>();
...
public void addTimePeriodBlock(TimePeriodBlock timePeriodBlock) {
timePeriodBlock.setTimePeriod(this);
this.timePeriodBlocks.add(timePeriodBlock);
}
...
With the following child relationship:
#Entity(name = "time_period_block")
public class TimePeriodBlock extends AbstractDomainObject {
...
#ManyToOne
#JoinColumn(name = "time_period_id", nullable = false)
private TimePeriod timePeriod;
...
They share this super class:
#MappedSuperclass
public abstract class AbstractDomainObject {
...
#Id
#GeneratedValue
#Column(name = "id", columnDefinition = "uuid", updatable = false)
private UUID id;
...
When I execute the following:
// pseudo code
TimePeriod t = new TimePeriod();
t.setName("test");
TimePeriodBlock b = new TimePeriodBlock();
t.addTimePeriodBlock(b);
em.persist(t);
I get the exception:
...
Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value : test.TimePeriodBlock.timePeriod
...
Some notes:
I strongly believe that this could be because Hibernate generates the UUID (and not the database) but, since I am not sure, I hope some fellow Developer might know how this could work.
I am using PostgreSQL 9.6 and the database can also generates UUIDv4 but requires compiling an extra extension so I opted for Hibernate to generate it.
When I enter some data in the database and retrieve the data it is fetched without any error.
Storing other objects without #ManyToOne relationships do store without any error and have a UUID that is generated by Hibernate.
Well after some debugging and using Luay Abdulreheem suggestion I found out that hibernate is working just fine; in this case my objects are send using a REST interface (using Jackson) and the reference to the parent was lost as the unmarshalling of the JSON is done using fields.
So nothing to see here, move along...
I'm trying to write a hibernate adapter for an old database schema. This schema does not have a dedicated id column, but uses about three other columns to join data.
On some tables, I need to use coalesce. This is what I came up with so far:
About the definition:
A car can have elements, assigned by the car's user or by the car's group of users.
If FORIGN_ELEMENT holds a user's name, definition will be 'u'
If FORIGN_ELEMENT holds a group's name, definition will be 'g'
This also means, one table (CAR_TO_ELEMENT) is misused to map cars to elements and cargroups to elements. I defined a superclass CarElement and subclasses CarUserElement and CarGroupElement.
state is either "active" or an uninteresting string
I set definitition and state elsewhere, we do not need to worry about this.
Use DEP_NR on the join table. If it's zero, use USR_DEP_NR. I did this with COALESCE(NULLIF()) successfully in native SQL and want to achieve the same in Hibernate with Pojos.
Okay, here we go with the code:
#Entity
#Table(name="CAR")
public class Car extends TableEntry implements Serializable {
#Id
#Column(name="DEP_NR")
private int depnr;
#Id
#Column(name="USER_NAME")
#Type(type="TrimmedString")
private String username;
#ManyToOne(fetch = FetchType.EAGER, targetEntity=CarGroup.class)
#JoinColumns(value={
#JoinColumn(name="GROUP_NAME"),
#JoinColumn(name="DEP_NR"),
#JoinColumn(name="state"),
})
private CarGroup group;
#OneToMany(fetch=FetchType.EAGER, targetEntity=CarUserElement.class, mappedBy="car")
private Set<CarUserElement> elements;
}
#Entity
#Table(name="CAR_GROUP")
public class CarGroup extends TableEntry implements Serializable {
#Id
#Column(name="DEP_NR")
private int depnr;
#Id
#Column(name="GROUP_NAME")
#Type(type="TrimmedString")
private String group;
#ManyToOne(fetch = FetchType.EAGER, targetEntity=Car.class)
#JoinColumns(value={
#JoinColumn(name="GROUP_NAME"),
#JoinColumn(name="DEP_NR"),
#JoinColumn(name="state"),
})
private Set<Car> cars;
#OneToMany(fetch=FetchType.EAGER, targetEntity=CarGroupElement.class, mappedBy="car")
private Set<CarGroupElement> elements;
}
#MappedSuperclass
public class CarElement extends TableEntry {
#Id
#ManyToOne(fetch = FetchType.EAGER, targetEntity=Element.class)
#JoinColumns(value={
#JoinColumn(name="ELEMENT_NAME"),
#JoinColumn(name="state"),
})
private Element element;
}
#Entity
#Table(name="CAR_TO_ELEMENT")
public class CarUserElement extends CarElement {
#Id
#Column(name="DEFINITION")
private char definition;
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumnsOrFormulas(value = {
#JoinColumnOrFormula(formula=#JoinFormula(value="COALESCE(NULLIF(DEP_NR, 0), USR_DEP_NR)", referencedColumnName="DEP_NR")),
#JoinColumnOrFormula(column=#JoinColumn(name="FORIGN_ELEMENT", referencedColumnName="USER_NAME")),
#JoinColumnOrFormula(column=#JoinColumn(name="STATE", referencedColumnName="STATE"))
})
private Car car;
}
#Entity
#Table(name="CAR_TO_ELEMENT")
public class CarGroupElement extends CarElement {
#Id
#Column(name="DEFINITION")
private char definition;
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumnsOrFormulas(value = {
#JoinColumnOrFormula(formula=#JoinFormula(value="COALESCE(NULLIF(DEP_NR, 0), USR_DEP_NR)", referencedColumnName="DEP_NR")),
#JoinColumnOrFormula(column=#JoinColumn(name="FORIGN_ELEMENT", referencedColumnName="GROUP_NAME")),
#JoinColumnOrFormula(column=#JoinColumn(name="STATE", referencedColumnName="STATE"))
})
private Car car;
}
I tried all available versions of hibernate (from 3.5.1 [first version with #JoinColumnsOrFormulas] up to 4.x.x), but I always get this error:
Exception in thread "main" java.lang.ClassCastException: org.hibernate.mapping.Formula cannot be cast to org.hibernate.mapping.Column
at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:351)
at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1338)
at org.hibernate.cfg.annotations.CollectionBinder.bindOneToManySecondPass(CollectionBinder.java:791)
at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:719)
at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:668)
at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:66)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1597)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1355)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1737)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1788)
Other hibernate users seem to have the same problem: They can't get it working with any version, see this thread and other stackoverflow questions:
https://forum.hibernate.org/viewtopic.php?f=1&t=1010559
To be more complete, here's my TrimmedString Class:
https://forum.hibernate.org/viewtopic.php?p=2191674&sid=049b85950db50a8bd145f9dac49a5f6e#p2191674
Thanks in advance!
PS: It works with joining just these three colulmns with just one DEP-NR-Column (i.e. either DEP_NR OR USR_DEP_NR using just #JoinColumns). But I need this coalesce(nullif()).
I ran into a similar problem, and it seems that the issue is that you are using a #Formula inside an #Id. Hibernate wants Ids to be insertable, and Formulas are read-only.
In my case I was able to work around the problem by making the individual columns Id properties on their own, and making the joined object a separate property. I don't know if this would work in your case since you're using two different columns in your formula, but if so your code might look something like:
#Entity
#Table(name="CAR_TO_ELEMENT")
public class CarUserElement extends CarElement {
#Id
#Column(name="DEFINITION")
private char definition;
#Id
#Column(name="DEP_NR")
private Integer depNr;
#Id
#Column(name="USR_DEP_NR")
private Integer usrDepNr;
#Id
#Column(name="FORIGN_ELEMENT")
private String userName;
#Id
#Column(name="STATE")
private String state;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumnsOrFormulas(value = {
#JoinColumnOrFormula(formula=#JoinFormula(value="COALESCE(NULLIF(DEP_NR, 0), USR_DEP_NR)", referencedColumnName="DEP_NR")),
#JoinColumnOrFormula(column=#JoinColumn(name="FORIGN_ELEMENT", referencedColumnName="USER_NAME", insertable = false, updatable = false)),
#JoinColumnOrFormula(column=#JoinColumn(name="STATE", referencedColumnName="STATE", insertable = false, updatable = false))
})
private Car car;
}
Join formulas are very fragile in Hibernate for the time being; I always had a difficult time to get them work properly.
The workaround that helped me often was to create database views which exposed the proper columns (including foreign keys that don't exist in the original tables). Then I mapped the entities to the views using classing Hibernate/JPA mappings.
Sometimes there are redundant joins in the generated SQL when using such entities, but the database optimizes such queries in most cases so that the execution plan is optimal anyway.
Another approach could be using #Subselects, which are some kind of Hibernate views, but I expect them to be less performant than the classic database views.
I ran into the cast exception as well and I'm on Hibernate 5.x.
Until Hibernate dedicates time to fix the issue, I found that while this guy's approach may not be cleanest (he even eludes to that fact!), it works.
You just need to add the #Column mappings (and get/set methods) to your association table objects that are returning null and manually set the values when you populate the relation data. Simple but effective!
I'm using Hibernate 3.5.2-FINAL with annotations to specify my persistence mappings. I'm struggling with modelling a relationship between an Application and a set of Platforms. Each application is available for a set of platforms.
From all the reading and searching I've done, I think I need to have the platform enum class be persisted as an Entity, and to have a join table to represent the many-to-many relationship. I want the relationship to be unidirectional at the object level, that is, I want to be able to get the list of platforms for a given application, but I don't need to find out the list of applications for a given platform.
Here are my simplified model classes:
#Entity
#Table(name = "TBL_PLATFORM")
public enum Platform {
Windows,
Mac,
Linux,
Other;
#Id
#GeneratedValue
#Column(name = "ID")
private Long id = null;
#Column(name = "NAME")
private String name;
private DevicePlatform() {
this.name = toString();
}
// Setters and getters for id and name...
}
#Entity
#Table(name = "TBL_APP")
public class Application extends AbstractEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "NAME")
protected String _name;
#ManyToMany(cascade = javax.persistence.CascadeType.ALL)
#Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
#JoinTable(name = "TBL_APP_PLATFORM",
joinColumns = #JoinColumn(name = "APP_ID"),
inverseJoinColumns = #JoinColumn(name = "PLATFORM_ID"))
#ElementCollection(targetClass=Platform.class)
protected Set<Platform> _platforms;
// Setters and getters...
}
When I run the Hibernate hbm2ddl tool, I see the following (I'm using MySQL):
create table TBL_APP_PLATFORM (
APP_ID bigint not null,
PLATFORM_ID bigint not null,
primary key (APP_ID, PLATFORM_ID)
);
The appropriate foreign keys are also created from this table to the application table and platform table. So far so good.
One problem I'm running into is when I try to persist an application object:
Application newApp = new Application();
newApp.setName("The Test Application");
Set<DevicePlatform> platforms = EnumSet.of(Platform.Windows, Platform.Linux);
newApp.setPlatforms(platforms);
applicationDao.addApplication(newApp);
What I would like to happen is for the appropriate rows in the Platform table to created, i.e. create a row for Windows and Linux, if they don't already exist. Then, a row for the new application should be created, and then the mapping between the new application and the two platforms in the join table.
One issue I'm running into is getting the following runtime exception:
2010-06-30 13:18:09,382 6613126-0 ERROR FlushingEventListener Could not synchronize database state with session org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.example.model.Platform
Somehow, the platform set is not being persisted when I try to persist the application. The cascade annotations are supposed to take care of that, but I don't know what's wrong.
So my questions are:
Is there a better way to model what I want to do, e.g. is using an Enum appropriate?
If my model is alright, how do I properly persist all of the objects?
I've been struggling with this for hours, and I've tried to recreate all of the code above, but it might not be complete and/or accurate. I'm hoping someone will point out something obvious!
You should decide whether your Platform is an entity or not.
If it's an entity, it can't be an enum, because list of possible platforms is stored in the database, not in the application. It should be a regular class with #Entity annotation and you will have a normal many-to-many relation.
If it isn't an entity, then you don't need TBL_PLATFORM table, and you don't have a many-to-many relation. In this case you can represent a set of Platforms either as an integer field with bit flags, or as a simple one-to-many relation. JPA 2.0 makes the latter case simple with #ElementCollection:
#ElementCollection(targetClass = Platform.class)
#CollectionTable(name = "TBL_APP_PLATFORM",
joinColumns = #JoinColumn(name = "APP_ID"))
#Column(name = "PLATFORM_ID")
protected Set<Platform> _platforms;
-
create table TBL_APP_PLATFORM (
APP_ID bigint not null,
PLATFORM_ID bigint not null, -- the ordinal number of enum value
primary key (APP_ID, PLATFORM_ID)
);
and enum Platform without annotations.
Simple use below mapping on your entity. Suppose that we have:
public enum TestEnum { A, B }
Then in your Entity class:
#ElementCollection(targetClass = TestEnum.class)
#CollectionTable(
name = "yourJoinTable",
joinColumns = #JoinColumn(name = "YourEntityId")
)
#Column(name = "EnumId")
private final Set<TestEnum> enumSet= new HashSet<>();
The following example shows what the situation is when Module is an entity and Langue is an enum.
#Entity
public class Module {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String libelle;
#ElementCollection(targetClass = Langue.class, fetch = FetchType.EAGER)
#CollectionTable(name = "link_module_langue",
joinColumns = #JoinColumn(name = "module_id", referencedColumnName = "id"))
#Enumerated(EnumType.STRING)
#Column(name = "langue")
private Set<Langue> langues;
}
public enum Langue {
FRANCAIS, ANGLAIS, ESPAGNOLE
}
You should create link_module_langue table, please see the following sql code :
CREATE TABLE `link_module_langue` (
`module_id` BIGINT(20) NOT NULL,
`langue` VARCHAR(45) NOT NULL,
PRIMARY KEY (`module_id`, `langue`),
CONSTRAINT `module_fk`
FOREIGN KEY (`module_id`)
REFERENCES `module` (`id`)
ON DELETE CASCADE
ON UPDATE CASCADE);
NB: Langue is not an entity and would not have its own table.