I am getting an exception with hibernate that I can't figure out.
org.hibernate.AnnotationException: Unable to create unique key constraint (role, username) on table user_roles: database column 'role' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)
I have defined the name of the column "role" with the annotation, am I missing something here?
Any help appreciated.
...
#Entity
#Table(name = "user_roles", uniqueConstraints = #UniqueConstraint(columnNames =
{ "role", "username" }) )
public class UserRole
{
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "user_role_id", unique = true, nullable = false)
private Integer userRoleId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "username", nullable = false)
private User user;
#Column(name = "role", nullable = false, length = 45)
private String role;
...
}
Related
the problems is when #ManyToOne make a #Joincolumn ID_REPORT (it´s a primary key ) and #Joincolumn ID_TEMPLATE_DEFAULT
Repeated column in mapping for entity: CurReport column: id_report (should be mapped with insert="false" update="false")
Code
First table CUR_TEMPLATE
CREATE TABLE CUR_TEMPLATE
(
ID_REPORT NUMBER(5,0) NOT NULL,
ID_TEMPLATE NUMBER(5,0) NOT NULL,
-- Other fields
);
ALTER TABLE CUR_TEMPLATE ADD CONSTRAINT PK_CUR_TEMPLATE PRIMARY KEY (ID_REPORT, ID_TEMPLATE)
-- CUR_TEMPLATE foreign keys
ALTER TABLE CUR_TEMPLATE ADD CONSTRAINT FK_CUR_PLAN_REFERENCE_CUR_REPO FOREIGN KEY (ID_REPORT)
REFERENCES CUR_REPORTS (ID_REPORT);
Second table CUR_REPORTS
-- CUR_REPORTS definition
CREATE TABLE CUR_REPORTS
(
ID_REPORT NUMBER(3,0) NOT NULL,
NAME_REPORT VARCHAR2(100) NOT NULL,
-- other fields
ID_TEMPLATE_DEFAULT NUMBER(5,0),
-- other fields
) ;
ALTER TABLE CUR_REPORTS ADD CONSTRAINT PK_CUR_REPORTS PRIMARY KEY (ID_REPORT)
ALTER TABLE CUR_REPORTS CONSTRAINT FK_CUR_REPO_REFERENCE_CUR_PLAN FOREIGN KEY (ID_REPORT, ID_TEMPLATE_DEFAULT)
REFERENCES CUR_TEMPLATE (ID_REPORT, ID_TEMPLATE)
First table CUR_REPORTS Entity CurReport
#Entity
#Table(name = "CUR_REPORTS")
#IdClass(CurPlantillaPK.class)
#Getter
#Setter
public class CurReport {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID_REPORT", nullable = false)
private Long id;
#Column(name = "NAME_REPORT", nullable = false, length = 100)
private String nombreReporte;
#ManyToOne(fetch = FetchType.LAZY) <---WHERE IS THE PROBLEM
#JoinColumn(name = "ID_REPORT", referencedColumnName = "ID_REPORTE")
#JoinColumn(name = "ID_TEMPLATE_DEFAULT", referencedColumnName = "ID_TEMPLATE")
private CurTemplate curTemplate;
#OneToMany(mappedBy = "curReport")
private Set<CurTemplate> curTemplates= new LinkedHashSet<>();
}
Second table CUR_TEMPLATE Entity CurReport
#Entity
#Table(name = "CUR_TEMPLATE")
#IdClass(CurPlantillaPK.class)
#Getter
#Setter
public class CurTemplate {
#Id
#Column(name = "ID_REPORT", nullable = false)
private Long idReport;
#Id
#Column(name = "ID_TEMPLATE", nullable = false)
private Long idTemplate;
#ManyToOne(optional = false, fetch = FetchType.LAZY)
#JoinColumn(name = "ID_REPORT", foreignKey = #ForeignKey(name = "FK_CUR_PLAN_REFERENCE_CUR_REPO"), referencedColumnName = "ID_REPORT", insertable = false, updatable = false)
private CurReport curReport;
}
When i add insertable=false, updatable=false
#JoinColumn(name = "ID_REPORT", referencedColumnName = "ID_REPORT", insertable=false, updatable=false)
said
Mixing insertable and non insertable columns in a property is not allowed: CurTemplate
How could i map those relationships?
How resolve the #JoinColumn when one field of the FK are column PK?
You can use a derived identity and map CurTemplate like this:
#Entity
#Table(name = "CUR_TEMPLATE")
#IdClass(CurTemplatePK.class)
#Getter
#Setter
public class CurTemplate {
#Id
#Column(name = "ID_TEMPLATE", nullable = false)
private Long idTemplate;
#Id
#ManyToOne(optional = false, fetch = FetchType.LAZY)
#JoinColumn(name = "ID_REPORT", foreignKey = #ForeignKey(name = "FK_CUR_PLAN_REFERENCE_CUR_REPO"), referencedColumnName = "ID_REPORT", insertable = false, updatable = false)
private CurReport curReport;
}
Then you will need an #IdClass like this:
public class CurTemplatePK {
Long idTemplate; // matches name of #Id attribute
Long curReport; // matches name of #Id attribute and type of CurReport PK
}
Then you should use a basic mapping for the default template key and provide a getter for the default template object:
#Entity
#Table(name = "CUR_REPORTS")
#IdClass(CurPlantillaPK.class)
#Getter
#Setter
public class CurReport {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID_REPORT", nullable = false)
private Long id;
#Column(name = "NAME_REPORT", nullable = false, length = 100)
private String nombreReporte;
#Column(name = "ID_TEMPLATE_DEFAULT")
private Long idDefaultTemplate;
#OneToMany(mappedBy = "curReport")
private Set<CurTemplate> curTemplates= new LinkedHashSet<>();
public CurTemplate getDefaultTemplate() {
return this.curTemplates.stream()
.filter(template -> template.getIdTemplate().equals(idDefaultTemplate))
.findFirst()
.orElse(null);
{
}
If you want to allow clients to set the default template, you will need to implement a setter that first verifies that the new default template is already in the set curTemplates.
I have the following 3 tables
table: project
id
company_code
number
contract_type_code
account_type_code
other columns…
table: contract_type
id
company_code
code
name
table: account_type
id
company_code
code
name
The project table references contract_type and account_type tables through contract_type_code/company_code and account_type_code/company_code respectively.
The company_code and code columns are what make a contract_type and account_type unique.
I'm struggling with modelling and mapping this in JPA. I've tried with the #JoinColumn and #JoinColumns annotation and there's no way for me to make it work.
This is one of the ways I've been trying with no success:
public class Project implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long companyCode;
private Long number;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name = "contract_type_code", referencedColumnName = "code"),
#JoinColumn(name = "company_code", referencedColumnName = "company_code")
})
private ContractType contractType;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name = "account_type_code", referencedColumnName = "code"),
#JoinColumn(name = "company_code", referencedColumnName = "company_code")
})
private AccountType accountType;
This is the issue I'm getting with the mapping above:
Caused by: org.hibernate.MappingException: Unable to find column with logical name company_code in table contract_type
For this mapping:
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name = "contract_type_code", referencedColumnName = "code", insertable = false, updatable = false),
#JoinColumn(name = "company_code", referencedColumnName = "company_code2", insertable = false, updatable = false)
})
private ContractType contractType;
I get:
Caused by: org.hibernate.DuplicateMappingException: Table [account] contains physical column name [company_code] referred to by multiple logical column names: [company_code], [companyCode]
I assume you have companyCode fields in the AccountType and ContractType. Annotate them as below (first error suggests JPA can't find them):
#Column(name = "company_code")
In your Project class modify companyCode field as follows (to avoid the second error):
#Column(name = "company")
private Long companyCode;
and keep mapping with:
insertable = false, updatable = false
Hope this will help. If not please add AccountType and ContractType classes to your question. Maybe then it will be easier to sort it out
I trying to map my class to database,the class reference to itself by "id_comment_parent", but when running a test, I get the following error:
Caused by: org.hibernate.AnnotationException: A Foreign key refering com.ecommerce.entities.Comment from com.ecommerce.entities.Comment has the wrong number of column. should be 2
at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:646) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:102) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processEndOfQueue(InFlightMetadataCollectorImpl.java:1814) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
these is my classe:
#Entity
#Table(name = "comment", catalog = "Ecommerce_db")
public class Comment implements Serializable {
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "idComment", column = #Column(name = "id_comment", nullable = false)),
#AttributeOverride(name = "idCommentParent", column = #Column(name = "id_comment_parent", nullable = false)) })
private CommentId id;
#Column(name = "id_user", nullable = false)
private long idUser;
#Column(name = "comment", length = 65535)
private String comment_1;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_comment_parent", nullable = false, insertable = false, updatable = false)
private Comment comment;
}
anyone have any idea?
Looks like CommentId that represents de Primary Key of Commenthas more that one column. So the ForeignKey must have more than one JoinColumn too.
Besides, it seems that you are mixing the fields of your primary key and your foreign key, as you have id_comment_parent in both primary key and foreign key.
You actually have comment entities with the same id_comment but with different id_comment_parent? It that's not the case, I think that a more coherent mapping would be that id_comment is the primary key, and id_comment_parent is the foreing key. Something like this:
#Entity
#Table(name = "comment", catalog = "Ecommerce_db")
public class Comment implements Serializable {
#Id
#Column(name = "id_comment", nullable = false)
private Long id;
#Column(name = "id_user", nullable = false)
private long idUser;
#Column(name = "comment", length = 65535)
private String comment_1;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_comment_parent")
private Comment parent;
}
I have a many to many User <-> Roles relation.
The User entity looks like this:
#Entity
#Table(name = "user",
uniqueConstraints = {#UniqueConstraint(columnNames = {"username", "email"})})
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, nullable = false)
private Long id;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "user_roles",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "role_id", referencedColumnName = "id"))
private Set<Role> roles = new HashSet<>();
}
And the Roles entity is the following:
#Entity
#Table(name = "role")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", updatable = true, nullable = false)
private Long id;
#Enumerated(EnumType.STRING)
#Column(length = 60, name = "roleName", updatable = true, nullable = false)
private RoleName roleName;
}
Everything works fine, except one thing. When I insert two users with the same role the roles table getting two records with the same role, but different IDs.
The question is, can I eliminate this behavior? Ideally the ROLES table should not contain duplicated roles.
Any advice would be appreciated. :)
I cannot find a problem in your entity mapping. The problem should be in the business logic where you try to save the user entity.
The problem you have described can happen if you set a not-yet-saved Role entity to a User. In other terms, your Role do not have an id field yet.
You need to get the Role from your persistent provider and set it to User.
If you are using spring-data, it can be like:
User user = ....
Role role = rolesRepository.findByName(roleName);
user.setRole(role);
// The persist User
i have a persit problem with elcipselink
here is my model :
#Entity
#Table(name = "TBL_ASSOC_LANGUE_CODE_BE_GARE")
public class AssocLangueCodeBeGare {
#AttributeOverrides({ #AttributeOverride(name = "id_langue", column = #Column(name = "ID_LANGUE") ),
#AttributeOverride(name = "id_gare", column = #Column(name = "ID_GARE") ) })
#EmbeddedId
private AssocLangueCodeBeGareFK key;
#Column(name = "CODE_BE", length = 4)
private String codeBe;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(nullable = false, name = "ID_GARE", referencedColumnName = "ID_GARE", insertable = false, updatable = false)
private StopPoint stopPoint;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ID_LANGUE", referencedColumnName = "ID_LANGUE", insertable = false, updatable = false)
private Langue langue;
in StopPoint i don t reference table AssocLangueCodeBeGare, i don t need it.
then when i do :
this.serviceStopPoint.save(currentStopPoint);
for (AssocLangueCodeBeGare assoc : listAssocLangueCodeBeGare) {
assoc.setStopPoint(currentStopPoint);
this.serviceAssocLangueCodeBeGare.save(assoc);
}
save is
#Override
public void save(T entityToSave) {
this.getEntityManager().persist(entityToSave);
}
I m using batch insert for writing and sometimes when i save another entity flush is done and i get :
Caused by: org.h2.jdbc.JdbcBatchUpdateException: NULL not allowed for column "ID_GARE"; SQL statement:
INSERT INTO TBL_ASSOC_LANGUE_CODE_BE_GARE (CODE_BE, ID_GARE, ID_LANGUE) VALUES (?, ?, ?) [23502-192]
at org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1208)
at org.eclipse.persistence.internal.databaseaccess.DatabasePlatform.executeBatch(DatabasePlatform.java:2134)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeJDK12BatchStatement(DatabaseAccessor.java:871)
does i miss something in the mapping?
does i need to add something like this in stoppoint entity:
#OneToMany(mappedBy = "stopPoint", cascade = CascadeType.ALL)
List<AssocLangueCodeBeGare> assocLangueCodeBeGares;
#EDIT1
I think its caused by my EmbeddedId because it was null!! the mapping does'nt set correct value in the embedable object?
here is the embedable object :
#Embeddable
public class AssocLangueCodeBeGareFK implements Serializable {
private String id_langue;
private Long id_gare;
#Override
public int hashCode() {
thanks a lot!
The insertable = false and updatable = false prevent the value from the mapping from being written to the database. You need to have another mapping to that database column with the value set, or it won't get into the database. While making your OneToMany the ID works, so would the MapsId annotation in the current code as JPA will then set the value in your embeddable ID. Or you could have manually added the value from the referenced class into the appropriate AssocLangueCodeBeGare.key fields.
Finaly i find a solution :
I use #IdClass(AssocLangueCodeBeGareFK.class on AssocLangueCodeBeGare
And i put #id on
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(nullable = false, name = "ID_GARE", referencedColumnName = "ID_GARE")
private StopPoint stopPoint;
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ID_LANGUE", referencedColumnName = "ID_LANGUE")
private Langue langue;
I rename on my AssocLangueCodeBeGareFK class name of my property to be the same as the AssocLangueCodeBeGare class :
private Long stopPoint;
private String langue;
now all work like a charm.
if it helps...