I'm using EJB 3 and JPA 2 in my application, i have 2 entities with many to relationship and want to persist them but fortunately after hours of searshing and trying i can't do it, so this is my code:
#Entity
public class Destinataire implements Serializable {
#Id
#Basic(optional = false)
#Size(min = 1, max = 50)
#Column(name = "ADRESSE")
private String adresse;
#OneToMany(mappedBy = "destinataire")
private Set<Envois> envoisSet;
//getters and setters
}
#Entity
public class Envois implements Serializable {
#EmbeddedId
protected EnvoisPK envoisPK = new EnvoisPK();
#Size(max = 4)
#Column(name = "TYPENVOIS")
private String typenvois;
#JoinColumn(name = "IDMAIL", referencedColumnName = "IDMAIL", insertable = false, updatable = false)
#ManyToOne(optional = false)
private MailAEnvoyer mailAEnvoyer;
#JoinColumn(name = "ADRESSE", referencedColumnName = "ADRESSE", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Destinataire destinataire;
}
#Embeddable
public class EnvoisPK implements Serializable {
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 255)
#Column(name = "ADRESSE")
private String adresse;
#Basic(optional = false)
#NotNull
#Column(name = "IDMAIL")
private BigDecimal idmail;
}
#Entity
#Table(name = "MAILAENVOYER")
public class MailAEnvoyer implements Serializable {
private static final long serialVersionUID = 1L;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Id
#Basic(optional = false)
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "IDMAIL")
private BigDecimal idmail;
#JoinTable(name = "ENVOIS", joinColumns = {
#JoinColumn(name = "IDMAIL", referencedColumnName = "IDMAIL")}, inverseJoinColumns = {
#JoinColumn(name = "ADRESSE", referencedColumnName = "ADRESSE")})
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
private Set<Destinataire> destinataireSet;
#OneToMany(mappedBy = "mailAEnvoyer", cascade = CascadeType.ALL)
private Set<Envois> envoisSet;
}
this is how i'm proceed :
Envois e = new Envois("CCI");
Destinataire dest = new Destinataire("adress");
destinataireService.create(dest);
e.setDestinataire(dest);
currentMailAEnvoyer.getEnvoisSet().add(e);
mailService.save(currentMailAEnvoyer);
but always i get an exception that EnvoisPK have adresse and idmail null,
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL into ("MAILING"."ENVOIS"."IDMAIL")
Error Code: 1400
Call: INSERT INTO ENVOIS (TYPENVOIS, IDMAIL, ADRESSE) VALUES (?, ?, ?)
bind => [3 parameters bound]
Query: InsertObjectQuery(entities.Envois[ envoisPK=entities.EnvoisPK[ adresse=null, idmail=null ] ])
you can add in the entity MailAEnvoyer the method below:
#PostPersist
public void postPersist() {
for (Envois e : envoisSet) {
e.getEnvoisPK().setIdmail(this.getIdmail());
}
}
Related
The "TypeMismatchException: Provided id of the wrong type" error thrown when tried to merge detached entity. It works if the object wasn't detached. It also works if ids aren't #EmbeddedId.
A sample repo can be found here https://github.com/joes-code/hibernate-map
// Asset.java
#Entity
#Table(name = "asset")
public class Asset {
#EmbeddedId
private AssetId id;
#Column(name = "asset_cost"
private BigDecimal price;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "asset_id", referencedColumnName = "asset_id", nullable = false, insertable = false, updatable = false, foreignKey = #ForeignKey(ConstraintMode.NO_CONSTRAINT))
private AssetDetail assetDetail;
}
// AssetId.java
#Embeddable
public class AssetId {
#Column(name = "asset_id", nullable = false)
private Integer assetId;
}
// AssetDetail.java
#Entity
#Table(name = "asset_detail")
public class AssetDetail {
#EmbeddedId
private AssetDetailId id;
#Column(name = "description", length = 35)
private String description;
}
// AssetDetailId.java
#Embeddable
public class AssetDetailId {
#Column(name = "asset_id", nullable = false)
private Integer assetId;
}
I'm using Hibernate 5.4.3.Final
Any ideas what I did wrong? It seems that Hibernate is assuming Asset and AssetDetail share the same Id class?
i have a weird issue : i'am trying to save a User in my DB, this user has a list of skills. those skills are already in the db with linked categories and categories have linked domains. the structure looks like this :
when i print the list of skills from the applicant i have this :
skills=[Skill{categories=[Category{domains=[Domain{id=4, name=DevOps}], id=13, name=BackEnd}], id=23, name=Java}, Skill{categories=[Category{domains=[Domain{id=4, name=DevOps}], id=13, name=BackEnd}], id=24, name=C}],
and here is the table making the link between Applicant and skills :
but when i'm trying to save the applicant i have this Détail : Failing row contains (23, null, null, 499). can someone explain me ? I'm working on a spring application using jpa annotaions.
EDIT 1 :
ApplicantEntity :
#Entity
#Table(name = "ATS_APPLICANT")
public class ApplicantEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "home", unique = false, nullable = true)
private Boolean home;
#Column(name = "anonymous", unique = false, nullable = true)
private Boolean anonymous;
#Enumerated(EnumType.STRING)
#Column(name = "job_type")
private JobType jobType;
#Column(name = "min_salary", unique = false, nullable = true)
private Integer minSalary;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(unique = true)
private UserEntity user;
#OneToMany(targetEntity = ApplicantWorkExperienceEntity.class, cascade = CascadeType.ALL)
private List<ApplicantWorkExperienceEntity> applicantWorkExperiences = new ArrayList<ApplicantWorkExperienceEntity>();
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
#JoinTable(name = "ATS_APPLICANT_SKILL", joinColumns = #JoinColumn(name = "applicant_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "skill_id", referencedColumnName = "id"))
private List<SkillEntity> skills = new ArrayList<SkillEntity>();
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "ATS_APPLICANT_LOCATION", joinColumns = #JoinColumn(name = "applicant_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "location_id", referencedColumnName = "id"))
private List<LocationEntity> locations = new ArrayList<LocationEntity>();
SkillEntity :
#Entity
#Table(name = "ATS_SKILL")
public class SkillEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotNull
#Size(min = 1, max = 42)
#Column(name = "name", length = 42, nullable = false, unique = true)
private String name;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "ATS_SKILL_CATEGORY", joinColumns = #JoinColumn(name = "skill_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "category_id", referencedColumnName = "id"))
private List<CategoryEntity> categories = new ArrayList<CategoryEntity>();
CategoryEntity :
#Entity
#Table(name = "ATS_CATEGORY")
public class CategoryEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotNull
#Size(min = 1, max = 42)
#Column(name = "name", length = 42, nullable = false, unique = true)
private String name;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "ATS_CATEGORY_DOMAIN", joinColumns = #JoinColumn(name = "category_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "domain_id", referencedColumnName = "id"))
private List<DomainEntity> domains = new ArrayList<DomainEntity>();
EDIT 2 :
DomainEntity :
#Entity
#Table(name = "ATS_DOMAIN")
public class DomainEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotNull
#Size(min = 1, max = 42)
#Column(name = "name", length = 42, nullable = false, unique = true)
private String name;
I succeed by using #ElementCollection annotation on skills.
I have a many-to-many relationship which looks like this:
The primary key is combination of three columns and I'm using eclipselink. I created these classes to be able to insert in the join-table :
#Entity
#Table(name = "definition_property")
#NamedQueries({
#NamedQuery(name = "DefinitionProperty.findAll", query = "SELECT d FROM DefinitionProperty d")})
public class DefinitionProperty extends AbstractEntity{
private static final long serialVersionUID = 1L;
#EmbeddedId
protected DefinitionPropertyPK pk;
#JoinColumn(name = "dtid", referencedColumnName = "id", insertable = false, updatable = false)
#ManyToOne(optional = false)
private DefinitionType definitionType;
#JoinColumn(name = "prid", referencedColumnName = "id", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Property property;
#Column(name = "initial_value")
#Basic(optional = false)
private String initialValue;
// setters and getters
}
And PK class:
#Embeddable
public class DefinitionPropertyPK implements Serializable{
#Column(name = "dtid")
private Integer idDt;
#Column(name = "prid")
private Integer idProperty;
#Column(name = "initial_value")
private String initialValue;
//hashcode, equals, setters and getters
}
Entitiy 1:
#Entity
#Table(name = "definition_type")
public class DefinitionType extends AbstractEntity implements EntityItem<Integer> {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer idDT;
#Size(max = 45)
#Column(name = "name")
private String dtName;
#Size(max = 45)
#Column(name = "description")
private String description;
#OneToMany(cascade=CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "definitionType")
private List<DefinitionProperty> definitionProperties = new ArrayList<DefinitionProperty>();
}
Entity 2:
#Entity
#Table(name = "property")
public class Property extends AbstractEntity implements EntityItem<Integer>{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE)
#Basic(optional = false )
#Column(name = "id")
private Integer idProperty;
#Column(name = "name")
#Size(max = 45)
private String propertyName;
#Enumerated(EnumType.STRING)
#Column(name = "type")
private Type fieldType;
#Column(name = "init_value")
#Size(max = 45)
private String initialValue;
#OneToMany(cascade=CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "property")
private List<DefinitionProperty> definitionPeoperties= new ArrayList<DefinitionProperty>();
}
Exception : I get this exception when trying to persist a new DefinitionType:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.microsoft.sqlserver.jdbc.SQLServerException: The column name 'initial_value' is specified more than once in the SET clause. A column cannot be assigned more than one value in the same SET clause. Modify the SET clause to make sure that a column is updated only once. If the SET clause updates columns of a view, then the column name 'initial_value' may appear twice in the view definition.
Error Code: 264
Call: INSERT INTO definition_property (initial_value, initial_value, dtid, prid) VALUES (?, ?, ?, ?)
bind => [4 parameters bound]
Question : Why there are two initial_values in the set clause and where am I wrong in my code?
Ref: How do you Set Up a Many-to-Many Relationship with Junction Table using JPA/EclipseLink
Ref: JPA simple many-to-many with eclipselink
Ref: https://giannigar.wordpress.com/2009/09/04/mapping-a-many-to-many-join-table-with-extra-column-using-jpa/
I'm starting with hibernate and I having some difficulties to build a easy
relationship of tables
, hibernate throw nested exception is org.hibernate.MappingException: Unable to find column with logical name: USERNAME in org.hibernate.mapping.Table(USER_FILESYSTEM) and its related supertables and secondary tables
I have this model
USER--1---N-->USER_FILE_SYSTEM--1--N-->USER_FS_THUMBS
All column name on DB squema are OK the column username" exists on table USER_FILESYSTEM
and table user
Table Users
#Entity
#Table(name = "USERS")
public class Users implements Serializable {
#Id
#Column(name = "USERNAME", nullable = false, length = 15)
private String username;
#Column(name = "PASSWORD", nullable = false, length = 64)
private String password;
#Column(name = "FIRSTNAME", length = 32)
private String firstname;
#Column(name = "LASTNAME", length = 32)
private String lastname;
#Column(name = "EMAIL", nullable = false, length = 60)
private String email;
#Column(name = "TELEPHONE", length = 50)
private String telephone;
#OneToOne(cascade = CascadeType.ALL)
#JoinTable(name = "USER_ROLE",
joinColumns = {
#JoinColumn(name = "USERNAME_ID", referencedColumnName = "USERNAME")},
inverseJoinColumns = {
#JoinColumn(name = "ROL_ID", referencedColumnName = "ROL")}
)
private Rol role;
#OneToMany(
fetch = FetchType.EAGER, mappedBy = "username"
)
private Set<UserFileSystem> fileSystem;
Table UserFileSystem
#Entity
#Table(name = "USER_FILESYSTEM")
public class UserFileSystem implements Serializable {
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "USERNAME", nullable = false)
private Users username;
#Id
#Column(name = "SERVICE_ID", nullable = false, length = 10)
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer serviceId;
#Id
#Column(name = "SERVICE_FOLDER", nullable = false, length = 64)
private String serviceFolder;
#Column(name = "PROTOCOL", length = 20)
private String protocol;
#Column(name = "PARAMS", length = 512)
private String params;
#OneToMany(
fetch = FetchType.LAZY, mappedBy = "userFileSystemThumbsPK"
)
private Set<UserFileSystemThumbs> fileSystemThumbs;
Table UserFileSystemThumbs
#Entity
#Table(name = "USER_FS_THUMBS")
public class UserFileSystemThumbs implements Serializable {
#EmbeddedId
private UserFileSystemThumbsPK userFileSystemThumbsPK;
#Column(name = "SERVICE_URL", nullable = false)
private String serviceUrl;
#Column(name = "CONTENT", nullable = false)
private byte[] content;
#Column(name = "MIME_TYPE", nullable = false)
private String mimeType;
Primary key entity UserFileSystemThumbs
#Embeddable
public class UserFileSystemThumbsPK implements Serializable {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name = "USERNAME", nullable = false, referencedColumnName = "USERNAME"),
#JoinColumn(name = "SERVICE_ID", nullable = false, referencedColumnName = "SERVICE_ID")
})
private UserFileSystem userFileSystem;
#Column(name = "SERVICE_URL_HASH", nullable = false)
private String serviceUrlHash;
Constructor equals hash....
the problem I think that UserFileSystemThumbsPK USERNAME column do reference to UserFileSystem but in this table the column USERNAME is provided by users.
Solution by OP.
I changed
#Entity
#Table(name = "USER_FILESYSTEM")
public class UserFileSystem implements Serializable {
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "USERNAME", nullable = false)
private Users username;
#Id
#Column(name = "SERVICE_ID", nullable = false, length = 10)
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer serviceId;
}
for this
#Entity
#Table(name = "USER_FILESYSTEM")
public class UserFileSystem implements Serializable {
#EmbeddedId
private UserFileSystemID userFSID;
}
and I created the object UserFileSystemID with 2 values of PK
It's working like a champ!
Would it be possible to declare a HashMap in the following object called Group?
Doing something like this doesn't work:
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "group")
#MapKey(name = "member.name")
private Map<String, GroupMember> groupMembers = new HashMap<String, GroupMember>();
StackTrace:
12:07:51 [INFO] [Groups] Enabling Groups v0.1
12:07:51 [SEVERE] Error occurred while enabling Groups v0.1 (Is it up to date?)
java.lang.RuntimeException: An exception has occured while initializing the database
at groups.storage.MyDatabase.initializeDatabase(MyDatabase.java:83)
at groups.storage.Dao.<init>(Dao.java:26)
at groups.Groups.onEnable(Groups.java:30)
at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:217)
at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:457)
at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:381)
at org.bukkit.craftbukkit.v1_5_R2.CraftServer.loadPlugin(CraftServer.java:282)
at org.bukkit.craftbukkit.v1_5_R2.CraftServer.enablePlugins(CraftServer.java:264)
at org.bukkit.craftbukkit.v1_5_R2.CraftServer.reload(CraftServer.java:605)
at org.bukkit.Bukkit.reload(Bukkit.java:184)
at org.bukkit.command.defaults.ReloadCommand.execute(ReloadCommand.java:23)
at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:188)
at org.bukkit.craftbukkit.v1_5_R2.CraftServer.dispatchCommand(CraftServer.java:523)
at org.bukkit.craftbukkit.v1_5_R2.CraftServer.dispatchServerCommand(CraftServer.java:512)
at net.minecraft.server.v1_5_R2.DedicatedServer.am(DedicatedServer.java:261)
at net.minecraft.server.v1_5_R2.DedicatedServer.r(DedicatedServer.java:226)
at net.minecraft.server.v1_5_R2.MinecraftServer.q(MinecraftServer.java:474)
at net.minecraft.server.v1_5_R2.MinecraftServer.run(MinecraftServer.java:407)
at net.minecraft.server.v1_5_R2.ThreadServerApplication.run(SourceFile:573)
Caused by: java.lang.RuntimeException: Failed to create a new instance of the EbeanServer
at groups.storage.MyDatabase.loadDatabase(MyDatabase.java:162)
at groups.storage.MyDatabase.initializeDatabase(MyDatabase.java:77)
... 18 more
Caused by: javax.persistence.PersistenceException: groups.model.Group: Could not find mapKey property [member.name] on [groups.model.GroupMember]
at com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany.initMapKeyProperty(BeanPropertyAssocMany.java:744)
at com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany.initialise(BeanPropertyAssocMany.java:147)
at com.avaje.ebeaninternal.server.deploy.BeanDescriptor.initialiseOther(BeanDescriptor.java:763)
at com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager.initialiseAll(BeanDescriptorManager.java:403)
at com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager.deploy(BeanDescriptorManager.java:293)
at com.avaje.ebeaninternal.server.core.InternalConfiguration.<init>(InternalConfiguration.java:150)
at com.avaje.ebeaninternal.server.core.DefaultServerFactory.createServer(DefaultServerFactory.java:209)
at com.avaje.ebeaninternal.server.core.DefaultServerFactory.createServer(DefaultServerFactory.java:64)
at com.avaje.ebean.EbeanServerFactory.create(EbeanServerFactory.java:78)
at groups.storage.MyDatabase.loadDatabase(MyDatabase.java:159)
... 19 more
...
#Entity
#Table(name = "groups_group")
public class Group {
public enum Type {
Include,
Exclude
}
#Id
#GeneratedValue
#Column(name = "id", unique = true, nullable = false)
private Integer id;
#Column(name = "name", unique = true, nullable = false, length = 25)
private String name;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "group")
#MapKey(name = "member.name")
private Map<String, GroupMember> groupMembers = new HashMap<String, GroupMember>();
#Column(name = "personal", nullable = false)
private Boolean personal = false;
#Enumerated(value = EnumType.ORDINAL)
#Column(name = "type", nullable = false, length = 2)
private Type type = Type.Include;
#Column(name = "password", nullable = true, length = 16)
private String password;
#Version
#Column(name = "update_time", nullable = false)
Timestamp updatetime;
#CreatedTimestamp
#Column(name = "create_time", nullable = false)
Timestamp createTime;
public Group() {}
//getters and setters
}
..
#Entity
#Table(name = "groups_group_member")
public class GroupMember {
public enum Role {
ADMIN,
MODERATOR,
MEMBER,
BANNED
}
#Id
#GeneratedValue
#Column(name = "id", unique = true, nullable = false)
private Integer id;
#ManyToOne
#JoinColumn(name = "group_id")
private Group group;
#ManyToOne
#JoinColumn(name = "member_id")
private Member member;
#Enumerated(value = EnumType.ORDINAL)
#Column(name = "role", nullable = false, length = 2)
private Role role = Role.MEMBER;
#Version
#Column(name = "update_time", nullable = false)
Timestamp updatetime;
#CreatedTimestamp
#Column(name = "create_time", nullable = false)
Timestamp createTime;
public GroupMember() {}
//getters and setters...
}
...
#Entity
#Table(name = "groups_member")
public class Member {
#Id
#GeneratedValue
#Column(name = "id", unique = true, nullable = false)
private Integer id;
#Column(name = "name", unique = true, nullable = false, length = 16)
private String name;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "member")
private Set<GroupMember> groupMembers = new HashSet<GroupMember>();
#Version
#Column(name = "update_time", nullable = false)
Timestamp updatetime;
#CreatedTimestamp
#Column(name = "create_time", nullable = false)
Timestamp createTime;
public Member() {}
//getters and setters
}