Hibernate creating Composite Key instead of using Identifier - java

I have an Entity FooBar which serves as the #ManyToMany join table for Foo and Bar entities including some additional information.
#Entity
#Table(name = "foo_bar")
public class FooBar
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", unique = true, nullable = false)
protected Long id;
#Column(name = "someInfo", nullable = true)
private String someInfo;
#ManyToOne(optional = false)
private Foo foo;
#ManyToOne(optional = false)
private Bar bar;
//getters, setters, and toString()
}
#Entity
#Table(name = "foo")
public class Foo
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", unique = true, nullable = false)
protected Long id;
#OneToMany(mappedBy = "foo", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<FooBar> fooBars;
//Foo has a number of other fields
#Column(name = "orderIndex", nullable = false)
private int orderIndex;
#Column(name = "upgradeDirection", nullable = false)
#Enumerated(EnumType.STRING)
private Order direction;
#ManyToOne(optional = false)
private SomeEntity e;
//getters, setters, and toString()
}
#Entity
#Table(name = "bar")
public class Bar
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", unique = true, nullable = false)
protected Long id;
#OneToMany(mappedBy = "bar") //TODO specify a cascade and fetch attribute
private Set<FooBar> fooBars;
//Bar contains a number of other fields
#Column(name = "value", nullable = false)
private String value;
//getters, setters, and toString()
}
When Hibernate creates the table is has columns 'id', 'someInfo', 'foo_id', and 'bar_id'. 'foo_id' and 'bar_id' are used in as a composite key instead of using the 'id' field, any idea why?

Related

hibernate OneToOne with EmbeddedId

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?

Inheritance in Hibernate. Inserting example

I want to make connection between Product class and Laptop
Product class
#Entity
#Table(name = "products")
#Inheritance(strategy = InheritanceType.JOINED)
public class Product {
#Id
#Column(unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column(nullable = false, unique = true)
private String name;
#Column(nullable = false)
private BigDecimal cost;
#Column(nullable = false)
private int count;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "productStatus", nullable = false)
private ProductStatus productStatus;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "productManufacture", nullable = false)
private ProductManufacture productManufacture;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "productCategory", nullable = false)
private ProductCategory productCategory;
and
Laptop class
#Entity
#Table(name = "laptops")
public class Laptop extends Product {
#Id
#Column(unique = true, nullable = false)
private int id;
#Column(nullable = false)
private String processor;
private int videoMemory;
#Column(nullable = false)
private int ram;
But my varient doesnt work...( How can I do it right
And how can I insert into database some data?(example please)
Laptop is extending Product class and inherits all the fields from the parent class including ID. You are defining ID again on the Laptop class. Inheritance Strategy is also JOINED which means it handles the Id generation both for the parent and the child class. Remove the Id field and its annotations.

JPA: Use a multiple One-to-many relationships with composite keys

I have these entities:
Run entity:
#Entity
#Table(name = "run")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "runId")
public class Run implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "run_id")
private Long runId;
#Column(name = "status")
private Integer status;
#Column(name = "create_date")
private Date date;
#Column(name = "config_id")
private Long configId;
#Column(name = "stream_id")
private Long streamId;
#OneToOne(mappedBy = "run", cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "run_id", unique = true, nullable = true, insertable = true, updatable = true)
private StreamRun streamRun;
...
}
and StreamRun entity:
#Entity
#Table(name = "stream_run")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "streamId")
public class StreamRun implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id")
private Long streamId;
#Column(name = "run_id", insertable = false, updatable = false)
private Long runId;
#Column(name = "stream_name")
private String streamName;
#OneToOne
#JoinColumn(name = "run_id")
private Run run;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "stream", orphanRemoval = true, targetEntity = JobRun.class)
private List<JobRun> jobs = new ArrayList<>();
#OneToMany(cascade = CascadeType.ALL, mappedBy = "streamRun", orphanRemoval = true, targetEntity = StreamEvent.class)
private List<StreamEvent> events = new ArrayList<>();
....
}
and JobRun entity:
#Entity
#Table(name = "jobs_run")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
#IdClass(JobRunKey.class)
public class JobRun implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id")
private Long id;
#Id
#Column(name = "run_id", insertable = false, updatable = false)
private Long runId;
#Column(name = "name")
private String name;
#Column(name = "type")
private String jobType;
#Column(name = "script")
private String script;
#Column(name = "status")
private Integer status;
#ManyToOne
#JoinColumns({ #JoinColumn(name = "run_id", referencedColumnName = "run_id"), #JoinColumn(name = "job_stream_id", referencedColumnName = "id") })
private StreamRun stream;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "jobRun", orphanRemoval = true, targetEntity = JobDependencyRun.class)
public List<JobDependencyRun> dependencies = new ArrayList<>();
#OneToMany(cascade = CascadeType.ALL, mappedBy = "jobRun", orphanRemoval = true, targetEntity = JobEvent.class)
public List<JobEvent> events = new ArrayList<>();
....
}
And all the columns are defined in the MySQL database, Table job_run have composite key of (id and run_id).
The problem is in JobRun entity:
If I define "run_id" field as #ID then an exception appear (when insert)
Parameter index out of range (8 > number of parameters, which is 7).
If I define it without #ID then an exception appear (when update)
Duplicate entry '4-78' for key 'PRIMARY'
If I remove the whole field definition from entity since it is foreign key then the exception will be:
Unable to find column with logical name run_id
"Although the column exists in the table".
Please, can anyone help me?
Do I do anything wrong in the code?
I have managed to find a solution, by modifying JobRun entity as below, and change\access the value of runId from direct setter and getter method.
#Entity
#Table(name = "jobs_run")
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
#IdClass(JobRunKey.class)
public class JobRun implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id")
private Long id;
#Id
#Column(name = "run_id")
private Long runId;
#Column(name = "job_stream_id")
private Long streamId;
#Column(name = "name")
private String name;
#Column(name = "type")
private String jobType;
#Column(name = "script")
private String script;
#Column(name = "status")
private Integer status;
#ManyToOne
#JoinColumns({ #JoinColumn(name = "run_id", referencedColumnName = "run_id", insertable = false, updatable = false),
#JoinColumn(name = "job_stream_id", referencedColumnName = "id", insertable = false, updatable = false) })
private StreamRun stream;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "jobRun", orphanRemoval = true, targetEntity = JobDependencyRun.class)
public List<JobDependencyRun> dependencies = new ArrayList<>();
#OneToMany(cascade = CascadeType.ALL, mappedBy = "jobRun", orphanRemoval = true, targetEntity = JobEvent.class)
public List<JobEvent> events = new ArrayList<>();
...
}

Transform MySQL select to Criteria API

I have the following select statement in MySQL (sorry for the column/tables names):
SELECT a1.* FROM A a1
LEFT JOIN A a2
ON a1.DD_ID = a2.DD_ID
and a1.PRD = a2.PRD
AND a1.VN < a2.VN
LEFT JOIN B bb
ON a1.id = cc.del_id
WHERE a2.DD_ID is null
AND bb.del_id is null;
Here are the entities:
#Entity
#Table(name = "A", uniqueConstraints = {
#UniqueConstraint(columnNames = {"DD_ID", "VN", "PRD"})})
public class A
implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID", unique = true, nullable = false)
private Long id;
#Column(name = "VN", nullable = false)
private Short vn;
#Column(name = "PRD", nullable = false)
#NotNull
private String prd;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "DD_ID", nullable = false)
#NotNull
private DD dd;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "A")
private Set<B> bs;
#Override
public boolean equals(final Object pOther)
{
...
}
#Override
public int hashCode()
{
...
}
// getters and setters
}
#Entity
#Table(name = "B")
public class B
implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID", unique = true, nullable = false)
private Long id;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "DEL_ID", nullable = false)
#NotNull
private A a;
#Override
public boolean equals(final Object pOther)
{
...
}
// getters and setters
}
and I want to implement it using Criteria API, but I have troubles implementing the self left join from the statement.
Any suggestions?

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