I have an entity with composite id , I'm using hibernate's Multiple id properties without identifier type , like so :
#Entity
class MyEntity implements Serializable {
#Id
private Long id1;
#Id
private Long id2;
//... Getters , setters , hashcode , equals ...
}
The problem is that in my Database: id1 = 1 , id2 = 2
And if I want to add a row with : id1 = 2 , id2 = 2
I get an error ConstraintViolationException: Duplicate entry '2' for key 'id2'
I'm using hibernate 4.1.7,
The documentation link : http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html_single/#mapping-declaration-id
Update
I'm talking about a Hibernate-specific solution: Map multiple properties as #Id properties without declaring an external class to be the identifier type
Use EmbeddedId. Please refer this.
It's very possible the problem is not your code, but your db schema. Without knowing what DBMS you're using and the constraints/indexes on the table for MyEntity, it's impossible to say for sure. However my guess is that you have something like this:
CREATE UNIQUE INDEX ON my_entity (id1);
CREATE UNIQUE INDEX ON my_entity (id2);
which requires that each column independently contains only unique values, when you really want something like this:
CREATE UNIQUE INDEX ON my_entity (id1, id2);
which allows each column to contain duplicates of the same value, as long as the combination of both columns is unique.
Related
I have database such as this:
CREATE TABLE unit
(
id INTEGER NOT NULL,
name VARCHAR,
);
CREATE TABLE unit_composition
(
parent_id INTEGER NOT NULL,
child_id INTEGER NOT NULL,
quantity INTEGER,
CONSTRAINT child_fk FOREIGN KEY (parent_id)
REFERENCES public.refdse (id) MATCH SIMPLE,
CONSTRAINT parent_fk FOREIGN KEY (parent_id)
REFERENCES public.refdse (id) MATCH SIMPLE
);
ALTER TABLE unit_composition
ADD CONSTRAINT composit_pk PRIMARY KEY (parent_id, art_nr);
I have a table of manufactory units. Each unit can have multiple sub-units, and sub-units can have multiple sub-sub-units and so on. Also I have a quantity field that shows how many sub-units are needed to manufactor a single unit. So it is kind of a tree relation.
Now I want to map it to classes with Spring Data. I have a Unit class with an Id and Name:
#Entity
#Table(name = "unit")
class Unit {
#Id
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
...
}
I've created a secondary class Part:
class Part {
private Unit unit;
private int quantity;
...
}
And I need unit class to have a field like List subUnits.
I tried to do it with a #SecondaryTable and #JoinColumn annotations, but I got an error saying "Relation unit_unit does not exist".
Also I tried to make Part an #Entity but it has no Id field.
Alternatively I tried to make #Embeddable class PartId and insert an instance into Part class like this:
#Embeddable
public class PartId implements Serializable {
private Unit parentUnit;
private Unit unit;
I'm getting an error in PartId class saying that "Basic type should not be Persistence Entity" because it's Embeddable and don't have a table assign to it.
So how can I make this work being able to get recursivly all sub-units (with sub-sub-units and so on) of a given Unit? I don't quite get it how can I map an entity that is really just links from table to itself.
So my first solution was to make Jdbc template repository and simply build necessary lists manually via SQL-queries. But I found much better and simplier solution that required adding an id column to unit_composition table and therefore making Part class an #Entity with #ManyToOne relationship to a Unit class. And the rest was simply done by Spring Data.
In my spring project, the tables in database are created automatically by Hibernate using my entity classes as base, but I insert some default values in the table manually (using pgAdmin3).
Because that, I am facing now this problem: when I try insert a value via Java code in one of the tables which already have values, I receive a error message, saying the primary key already exists in the database.
Anyone knows how to solve this problem?
UPDATE
That's how I declare my primary key in my class:
#Id
#Column(name = "id")
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
Call this SQL query once per table to set the sequence to the next free number:
SELECT setval('tblname_id_seq', max(id)) FROM tblname;
tblname being the actual name of the table.
Hibernate may use a different naming convention, or the sequence may have been renamed. If you can't find the sequence behind the serial column, check with (per documentation):
SELECT pg_get_serial_sequence(tblname, column_name)
More details:
Modify Django AutoField start value
How to import a CSV to postgresql that already has ID's assigned?
The problem here might be that you declare the id as a primitive instead of a wrapper.
So instead of:
private int id;
You should have:
private Integer id;
When you create the entity with the id is initialized as 0, instead of NULL.
That's why you get duplicate id constraint violation exceptions.
Only when the id is NULL the AUTO generation strategy will delegate the id assignment to the database.
in JPA2 when we are using Embed-able (Basic Type like String.. etc ) object in Entity using with #ElementCollection and #CollectionTable annotation , the new table is created , but in new table how to declare primary-key contraint in column ? following is my code
public class Employee {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
private String salary;
#Transient
private String phnNum;
#Enumerated(EnumType.STRING)
private EmployeeType type;
#ElementCollection
#CollectionTable(name="vacations" , joinColumns=#JoinColumn(name="Emp_Id"))
private Collection<Vacation> vacationBooking;
#ElementCollection
private Set<String> nickNames;
...................
with this code the "vacation" and "employee_nickname" two tables are created in schema. but i want to declare the one primary-key column in both table . what i do for this?
It looks like a primary key per se is not supported by JPA 2.0:
From Wikibooks:
The JPA 2.0 specification does not provide a way to define the Id in the Embeddable. However, to delete or update an element of the ElementCollection mapping, some unique key is normally required. Otherwise, on every update the JPA provider would need to delete everything from the CollectionTable for the Entity, and then insert the values back. So, the JPA provider will most likely assume that the combination of all of the fields in the Embeddable are unique, in combination with the foreign key (JoinColumn(s)). This however could be inefficient, or just not feasible if the Embeddable is big, or complex.
Some JPA providers may allow the Id to be specified in the Embeddable, to resolve this issue. Note in this case the Id only needs to be unique for the collection, not the table, as the foreign key is included. Some may also allow the unique option on the CollectionTable to be used for this. Otherwise, if your Embeddable is complex, you may consider making it an Entity and use a OneToMany instead.
Do you mean that you want to assign 'id' from Employee table as foreign key to the Vacation table?
In that case, you should use #OneToMany instead of #ElementCollection
I have 2 legacy tables:
CREATE TABLE A (
ID NUMBER PRIMARY KEY ,
DATA NUMBER
)
CREATE TABLE A_CONF (
A_ID NUMBER, // FK to A
INFO VARCHAR2(256)
)
Creating the JPA entity for A is straightforward. Yet, what can I do retrieve the multiple INFO fields that can be associated to an instance of A since there is no PK in A_CONF and therefore cannot create an entity for it?
Thanks for helping.
Seems like you are looking for what JPA calls an "element collection":
#Entity
public class A {
#Id
private Long id;
private Long data;
#ElementCollection
#CollectionTable(name="A_CONF", joinColumns=#JoinColumn(name="A_ID")) // A_ID would be the default join column
#Column(name="INFO")
private Set<String> infos; // using Set assuming unique values
}
You can define a primary key in your model class even if your table doesn't have one, just pick one or some columns in your model and put them as ids.
I have a question about Hibernate ManyToMany mappings. I have two classes A and B and the mapping between them is a ManyToMany mapping resolved by Hibernate:
#Entity
#Table(name="A")
public class A {
#Id
#GeneratedValue
private Long id;
#ManyToMany
#JoinTable(name="C", joinColumns=#JoinColumn(name="a_id"), inverseJoinColumns=#JoinColumn(name="b_id"))
private Set bs;
}
#Entity
#Table(name="B")
public class B {
#Id
#GeneratedValue
private Long id;
#ManyToMany(mappedBy="bs")
private Set bs;
}
As you can see, the Join Table I use is C. The foreign keys to A and B are "a_id" and "b_id". My understanding is, that Hibernate creates a composed Primary Key with a_id and b_id for table C.
I don't want to have an entity C in my model. But instead of a composed primary key on table C, I would like to have a generated ID and a unique constraint on the fields a_id and b_id.
Is it possible to tell Hibernate to use a separate primary key? Without adding an entity C?
I would appreciate any help.
Thanks a lot!
You should do iyt like this. But it can be appled only for list (not for sets)
#Entity
#TableGenerator(name="ids_generator", table="IDS")
public class Passport {
...
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name="PASSPORT_VISASTAMP")
#CollectionId(
columns = #Column(name="COLLECTION_ID"),
type=#Type(type="long"),
generator = "ids_generator"
)
private Collection<Stamp> visaStamp = new ArrayList();
...
}
I don't think it is possible. And I don't see a problem in defining a C entity.
If you have any additional information ind the join-table, it will not be accessible to you, because your Set contains the target entity - A or B.
Also, your Sets would better make use of generics - i.e. Set<A> and Set<B>.
Btw, Hibernate might not be alarmed by the fact that the table creates another entity - using your current mapping might work (disregarding completely the id column). When you said "Hibernate creates", I assumed you are generating your schema from your entity model. Now it seems it's the opposite, so give it a try.
But instead of a composed primary key on table C, I would like to have a generated ID and a unique constraint on the fields a_id and b_id.
Normally the primary key of the JoinTable is made of the combination of both foreign keys. At least, this is what JPA would generate. But if you don't use the JPA provider to generate the model and if the PK can be generated by the database (using an IDENTITY column, a trigger, etc), then you should be able to use the C table for your ManyToMany association (without having to introduce an extra entity and to transform the relation in two OneToMany). Did you actually try?