Hibernate AttributeOverride annotation error - java

I have following entities:
public class MyEntity extends AuditableEntity {
#Column
private String name;
}
AuditableEntity class:
public class AuditableEntity {
#Id
#GenericGenerator(name = "uuid-gen", strategy = "uuid2")
#GeneratedValue(generator = "uuid-gen", strategy = GenerationType.IDENTITY)
private String id;
#CreatedBy
#JsonIgnore
#Embedded
#AttributeOverrides({
#AttributeOverride(name = "user", column = #Column(name = "created_by_id")),
#AttributeOverride(name = "clientId", column = #Column(name = "created_by_client_id"))
})
private AuditorDetails createdBy;
#LastModifiedBy
#JsonIgnore
#Embedded
#AttributeOverrides({
#AttributeOverride(name = "user", column = #Column(name = "last_modified_by_id")),
#AttributeOverride(name = "clientId", column = #Column(name = "last_modified_by_client_id"))
})
private AuditorDetails lastModifiedBy;
}
And my AuditorDetails class:
#Embeddable
public class AuditorDetails {
#Column(name = "auditor_client_id")
private String clientId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn
private User user;
}
Also, I have AuditorAware that returns AuditorDetails object. When I try to run this, I have following exception:
org.hibernate.MappingException: Repeated column in mapping for entity:
com.aaa.MyEntity column: user_id (should be mapped with insert="false"
update="false")
But I can't make this column(s) not updatable and not insertable. The main goal is to have in MyEntity 4 columns - created_by_id, created_by_client_id, last_modified_by_id, last_modified_by_client_id that will contain all data about row modification and creation. How to fix this exception?

I have fixed this issue just adding annotations AssociationOverrides:
#CreatedBy
#JsonIgnore
#Embedded
#AssociationOverrides({
#AssociationOverride(name = "user", joinColumns = #JoinColumn(name = "created_by_id"))
})
#AttributeOverrides({
#AttributeOverride(name = "user", column = #Column(name = "created_by_id")),
#AttributeOverride(name = "clientId", column = #Column(name = "created_by_client_id"))
})
private AuditorDetails createdBy;
#LastModifiedBy
#JsonIgnore
#Embedded
#AssociationOverrides({
#AssociationOverride(name = "user", joinColumns = #JoinColumn(name = "last_modified_by_id"))
})
#AttributeOverrides({
#AttributeOverride(name = "user", column = #Column(name = "last_modified_by_id")),
#AttributeOverride(name = "clientId", column = #Column(name = "last_modified_by_client_id"))
})
private AuditorDetails lastModifiedBy;

Related

Java Spring: ManytoOne EmbeddedId in child class with additional Id - getting null error on child specific PK

I was able to get this ManyToOne relationship with a composite pk working for GET requests but I am having issues with saving new entries.
I have a parent entity with an embedded id.
#Embeddable
public class AnnualServiceHistoryPK implements Serializable {
#Column(name = "year", columnDefinition = "int(4)")
Integer year;
#Column(name = "month", columnDefinition = "char(3)")
String month;
#Column(name = "route", columnDefinition = "varchar(32)")
String route;
This is placed in the parent entity:
#Entity(name = "AnnualServiceHistory")
#Table(name = "annual_service_history")
public class AnnualServiceHistory extends Auditable<String> implements Serializable
{
#EmbeddedId
AnnualServiceHistoryPK annualServiceHistoryPK;
... other variables
#OneToMany(mappedBy = "annualServiceHistory", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
List<AnnualServiceHistoryNonMachine> annualServiceHistoryNonMachineList;
I have the child entity which maps the embedded id from the parent and adds and additional local PK.
public class AnnualServiceHistoryNonMachine extends Auditable<String> implements Serializable {
#Id
#MapsId
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "year", referencedColumnName = "year")
#JoinColumn(name = "month", referencedColumnName = "month")
#JoinColumn(name = "route", referencedColumnName = "route")
private AnnualServiceHistory annualServiceHistory;
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "toy_inventory", referencedColumnName = "id")
ToyInventory toyInventory;
... other variables
My issue is, when I save the parent with a list of children for some reason during the cascading processes, when it is generating the child key it is only creating the key from the MapsId parts and complains that the toyInventory key is null. I'm not sure why it loses this ID because prior to performing the repository save the child class has the toyInventory key in the object.
This is the error I am receiving:
"java.sql.SQLIntegrityConstraintViolationException: Column 'toy_inventory' cannot be null"
Solution found. - https://medium.com/#bhagyajayashani/composite-key-handling-using-idclass-annotation-in-spring-boot-java-26f40bbd38a2
Changed from using #embeddedId to using #classId. Then created a separate join object, and created join based off individual variables not the embeddedId.
#Embeddable
public class AnnualServiceHistoryPK implements Serializable {
Integer year;
String month;
String route;
public AnnualServiceHistoryPK() {
}
#Entity(name = "AnnualServiceHistory")
#Table(name = "annual_service_history")
#IdClass(AnnualServiceHistoryPK.class)
public class AnnualServiceHistory extends Auditable<String> implements Serializable {
#Id
#Column(name = "year", columnDefinition = "int(4)")
Integer year;
#Id
#Column(name = "month", columnDefinition = "char(3)")
String month;
#Id
#Column(name = "route", columnDefinition = "varchar(32)")
String route;
... other variables ...
#OneToMany(mappedBy = "annualServiceHistory", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
Set<AnnualServiceHistoryNonMachine> annualServiceHistoryNonMachineList;
#Embeddable
public class AnnualServiceHistoryNonMachinePK implements Serializable {
Integer year;
String month;
String route;
ToyInventory toyInventory;
public AnnualServiceHistoryNonMachinePK() {
}
#Entity(name = "AnnualServiceHistoryNonMachine")
#Table(name = "annual_service_history_non_machine")
#IdClass(AnnualServiceHistoryNonMachinePK.class)
public class AnnualServiceHistoryNonMachine extends Auditable<String> implements Serializable {
#Id
#Column(name = "year", columnDefinition = "int(4)")
Integer year;
#Id
#Column(name = "month", columnDefinition = "char(3)")
String month;
#Id
#Column(name = "route", columnDefinition = "varchar(32)")
String route;
... other variables ...
#ManyToOne
#JoinColumns({
#JoinColumn(name = "year", referencedColumnName = "year", insertable = false, updatable = false),
#JoinColumn(name = "month", referencedColumnName = "month", insertable = false, updatable = false),
#JoinColumn(name = "route", referencedColumnName = "route", insertable = false, updatable = false)
})
#JsonIgnore
private AnnualServiceHistory annualServiceHistory;

Unable to use #NamedEntityGraph with #ElementCollecion

I'm trying to set simple entity with NamedEntityGraph on it. Unfortunately it won't work. Could you have any ideas how to fix it?
ServiceType entity has #ElementCollection of with Set of String which are simply ids of PictureModel associated with entity. On run I got:
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [backgroundPicIds] on this ManagedType [pl.mihome.djcost.model.ServiceType]
#Entity
#Table(name = "service_type")
#Getter
#Setter
#NoArgsConstructor
#NamedEntityGraph(
name = "serviceType.with.backgroundPicIds",
attributeNodes = #NamedAttributeNode("backgroundPicIds")
)
public class ServiceType {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Setter(AccessLevel.NONE)
#Column(nullable = false, updatable = false)
private int id;
#Length(max = 100)
#NotBlank
private String name;
private boolean active;
#OneToMany(mappedBy = "serviceType")
private Set<Account> accounts;
#ManyToMany(mappedBy = "servicesApplicable")
private Set<AccountType> accountTypes;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "serviceType", orphanRemoval = true, cascade = CascadeType.ALL)
private Set<PictureModel> backgroundPicture;
#ElementCollection
#CollectionTable(name = "image", joinColumns = {#JoinColumn(name = "service_type_id")})
#Column(name = "id")
private Set<String> backgroundPictureId;
#PrePersist
void activate() {
this.active = true;
}
}
#Entity
#Table(name = "image")
#NoArgsConstructor
#Getter
#Setter
#Builder
#AllArgsConstructor
public class PictureModel {
#Id
#GeneratedValue(generator = "UUID")
#GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
#Column(nullable = false, updatable = false)
#Setter(AccessLevel.NONE)
private String id;
private String type;
private String name;
#Lob
private byte[] body;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "account_id")
private Account account;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "public_platform_id")
private PublicPlatform publicPlatform;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "service_type_id")
private ServiceType serviceType;
}
You simply do not have an attribute with the name backgroundPicIds in the entity ServiceType.
Try to correct your graph in this way:
#NamedEntityGraph(
name = "serviceType.with.backgroundPicIds",
attributeNodes = #NamedAttributeNode("backgroundPictureId")
)

JdbcSQLSyntaxErrorException: Syntax error in SQL statement "DROP TABLE PUBLIC.PRODUCTS-[*]USERS IF EXISTS "

I'm trying to write tests and using in memory DB. My problem is to create schema for tests from hibernate entities.
I have such entities
#Entity
#Table(name = "users", schema = "public")
#Getter
#Setter
#NoArgsConstructor
public class User {
#Id
#Column(name = "user_id", updatable = false, nullable = false, unique = true)
#GeneratedValue(generator = "UUID")
#GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
#Column(name = "name")
private String name;
#Column(name = "product")
#ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
#JoinTable(name = "products_users",
joinColumns = {#JoinColumn(name = "user_id")},
inverseJoinColumns = {#JoinColumn(name = "product_id")})
private Set<Product> products;
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd#HH:mm:ss")
#Column(name = "created_on")
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private Date createdOn;
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd#HH:mm:ss")
#Column(name = "modified_on")
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private Date modifiedOn;
public User(String name, Set<Product> products, Date createdOn, Date modifiedOn) {
this.name = name;
this.products = products;
this.createdOn = createdOn;
this.modifiedOn = modifiedOn;
}
}
#Entity
#Table(name = "product", schema = "public")
#Getter
#Setter
#NoArgsConstructor
public class Product {
#Id
#Column(name = "product_id", updatable = false, nullable = false, unique = true)
#GeneratedValue(generator = "UUID")
#GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
#Column(name = "name")
private String name;
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd#HH:mm:ss")
#Column(name = "created_on")
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private Date createdOn;
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd#HH:mm:ss")
#Column(name = "modified_on")
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private Date modifiedOn;
public Product(String name, Date createdOn, Date modifiedOn) {
this.name = name;
this.createdOn = createdOn;
this.modifiedOn = modifiedOn;
}
}
#Entity
#Table(name = "products_users", schema = "public")
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class ProductsUsers {
#Id
#Column(name = "user_id", updatable = false, nullable = false, unique = true)
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private UUID userId;
#Column(name = "product_id")
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private UUID productId;
}
and
application.properties
spring.output.ansi.enabled=ALWAYS
server.port=8081
debug=true
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=123
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=false
And I have
application.properties
in tests package
spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS public;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
spring.jpa.properties.hibernate.default_schema=public
And I get such exception
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error
executing DDL "alter table "public"."products_users" drop constraint
"FK2w1ylwiyjuy67n1ycr5lv5or3"" via JDBC Statement
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table
"products_users" not found; SQL statement: alter table
"public"."products_users" drop constraint
"FK2w1ylwiyjuy67n1ycr5lv5or3"

How to map entities with #EmbeddedId?

Does anyone know how to fix the mapping of entities?
Error is
Caused by: org.hibernate.AnnotationException: Column name ID of
com.test.TableAa not found in JoinColumns.referencedColumnName.
TableAa entity
#Entity
#Table(name = "TABLE_AA")
public class TableAa {
#EmbeddedId
private TableAaPk pk;
#Column(name = "FIRST_NAME")
private String first_name;
#Column(name = "LAST_NAME")
private String last_name;
//#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
//#JoinColumns({
//#JoinColumn(name = "ID", referencedColumnName = "ID", insertable = false, updatable = false),
//#JoinColumn(name = "ACCOUNT_NUMBER", referencedColumnName = "ACCOUNT_NUMBER", insertable = false, updatable = false) })
#OneToMany(mappedBy = "tableAa", cascade = CascadeType.ALL)
private List<TableBb> tableBbList;
}
TableAaPk composite key
#Embeddable
public class TableAaPk implements Serializable{
private static final long serialVersionUID = 1L;
#Column(name="ID")
private String id;
#Column(name="ACCOUNT_NUMBER")
private String accountNumber;
}
TableBb entity
#Entity
#Table(name = "TABLE_BB")
public class TableBb {
#EmbeddedId
private TableBbPk pk;
#Column(name = "FIRST_NAME")
private String first_name;
#Column(name = "LAST_NAME")
private String last_name;
}
TableBbPk composite key
#Embeddable
public class TableBbPk implements Serializable{
private static final long serialVersionUID = 1L;
#Column(name="ID")
private String id;
#Column(name="ACCOUNT_NUMBER")
private String accountNumber;
#Column(name="CODE")
private String code;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name = "ID", referencedColumnName = "ID", insertable = false, updatable = false),
#JoinColumn(name = "ACCOUNT_NUMBER", referencedColumnName = "ACCOUNT_NUMBER", insertable = false, updatable = false) })
private TableAa tableAa;
}
In your TAbleAa you should have your OneToMany mapping as follows:
#OneToMany(mappedBy = "pk.tableAa", cascade = CascadeType.ALL)
private List<TableBb> tableBbList;
You reference through the embeddable which name is pk.
I think your problem in this entity
#Entity
#Table(name = "TABLE_BB")
public class TableBb {
#EmbeddedId
private TableBbPk pk;
#Column(name = "FIRST_NAME")
private String first_name;
#Column(name = "LAST_NAME")
private String last_name;
// I think the solution is to add the relation #ManyToOne which mapped by in the other side
#ManyToOne // because u refere to this name (tableAa) in #OneToMany(mappedBy = "tableAa"...) in TableAa entity
private TableAa tableAa;
}

Hibernate Many To one 3 table involved

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!

Categories