I hava a spring-boot application that makes CRUD operations on a mysql datebase.
In thid db, there are two tables 'Employee' and 'Employee_departament' (both with auto-increment primary key and employee_id is foreign key in Employee_departament).
When I add a new employee in Employee table it will generate a record with id = 1. After that, if I add a new record in Employee_departament, this one will have id = 2.
This looks like my tables are sharing id column.
If you are using #GeneratedValue(strategy = GenerationType.SEQUENCE) above the id fields in both of your entities then they will both use the default database sequence (named hibernate_sequence) to generate new ids. This results in the behavior that you are describing.
If you want the entities to have their ids generated from separate sequences, you can specify the name of the sequence to get the ids by specifying the generator value inside of the GeneratedValue annotation. For example:
Employee.java
#Entity
#Table(name = "employee")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "employee_seq")
private Long employee_id;
...
EmployeeDepartment.java
#Entity
#Table(name = "employee_department")
public class EmployeeDepartment {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "employee_department_seq")
private Long employee_department_id;
...
Please add these two annotations into your entity class id attribute
#GeneratedValue(strategy = GenerationType.AUTO)
#Access(AccessType.PROPERTY)
Related
I use spring boot/jpa/hibernate/MYSQL to generate schema and have table orders. I want generate 2 sequence in one table. First generated second ignored. How I could achieve that?
#Entity
#Data
#Table(name = "orders")
public class Orders {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
#Column(name = "order_number")
#GeneratedValue(strategy= GenerationType.AUTO)
private Long orderNumber;
}
The implementation of #GeneratedValue with the AUTO strategy in your actual SQL database will likely be to use an auto increment column. Most databases do not even allow having two auto increment columns, and in general, there should not be a need why you even would need this. I suggest just deleting one of either the id or orderNumber fields, and keeping the other one as the only auto increment column in your entity/table.
I am begginer in Hibernate and i have a table named suffrages1 with no relations to the rest of the database.
The table has an autoincrement identifier field named Suffrages_id.
In the corresponding entity, i am declaring the field as follows :
#Entity(name = "suffrages1")
public class Suffrage1 implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#JoinColumn(name = "Suffrages_id")
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
The insertion is fine but when i try to fetch i get this error :Unknown column 'this_.id' in 'field list'
All similar issues i found were about problems with relationships between tables or about correct column names for mapping but as i said this table has no relationship with other table and i think i have the correct names e,g i know that my Java variable in the class is named id but is annotated with #JoinColumn to correspond to the Mysql column. So where did 'this_.id' come from ?
Sorry, i was using #JoinColumn instead of #Column to define the id field.
Am using springboot with hibernate,
My Entity classes looks like below :
#Entity
#Table(name="tbl_user")
public class User {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="user_Id")
private long userId;
#Column(name="userName")
private String userName;
#Column(name="passWord")
private String passWord;
#OneToMany(cascade = CascadeType.ALL)
#JoinTable(name="user_role")
private Collection<Role> roleList;
My second entity looks like below :
#Entity
#Table(name="tbl_role")
public class Role {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="role_Id")
private long roleId;
#Column(name="roleName")
private String roleName;
When I insert first user with role as manager(pkid=1), admin(pkid=2) its success but while I tried to insert 2nd user with role as Manager*pkid=1, admin(pkid=2, serviceUser(pkid=3) it's not allowing me to insert second user with below exception
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '2' for key 'UK_ixctfj5iq0enl7iktlpo7wxct'
Can somebody help me why this constraint is getting creating while generating tables, how can i insert 2nd user into DB ?
If you use OnetoMany on role_list you are effectively saying that a single User will point to many Roles and that a Role will point to only one User. This will be enforced with a unique key constraint placed on the join table. If you have the SQL statements printed out you will see it when the schema is created. Something along the lines of:
alter table user_role add constraint UK_ixctfj5iq0enl7iktlpo7wxct unique (role_id)
In your requirement, you also have a single Role used by many Users. Your admin role primary key is 2 and you want to be able to assign it to more than one user. Your relationship is a ManyToMany for the role_list.
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name="user_role")
private Collection<Role> roleList;
When you change the annotation, you will still have a join table, but no constraint will be added.
I am confused about how the JPA handles a 1:1 unidirectional relationship when I auto generate my tables from my entity classes vs. how I would make those tables if I was creating the SQL tables myself.
My question concerns how the foreign keys are set up.
Assuming I have a Customer entity and an Address entity like this:
#Entity
public class Customer{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#OneToOne(cascade = CascadeType.ALL)
private Address address;
//setters and getters
}
#Entity
public class Address{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String streetName;
//setters and getters
}
If I generate the sql tables from these two entity classes then the Customer table will have a foreign key column referencing the Address table.
Is there a way to have a OneToOne unidirectional relationship where the JPA sticks the foreign key on the target table(the address table) instead of on the Customer table as it does in my code example, or do I have to make it a bidirectional relationship and show more explicit ownership with the #Mapping annotation to achieve this kind of table structure?
To have the foreign key appear on the other table for a 1-1 unidirectional relationship you would need to switch the 'owning' side: place customer in Address and remove address from Customer. Then the foreign key for customer would be in the address table.
First of all, you have to map your address_id(or something like that) from the Customer entity. For example using below code, you are referencing the Address from the Customer.
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="ADDRESS_ID")
private Address address;
While deleting any entry from the address table, you must first delete the entry from the Customer table in order to avoid the foreign key violation error. Then you can delete from Address table. JPA doesn't handle this relationship while deleting any row from table.
I know this makes none sense as many tutorials state that you can use SecondaryTable annotation, however it doesn't work in hibernate. I have schema like this:
#Entity
#Table(name="server")
#SecondaryTable(name="cluster", pkJoinColumns = { #PrimaryKeyJoinColumn(name = "uuid", referencedColumnName = "cluster_uuid") })
public class Server {
#Id
#Column(name = "uuid")
private String uuid;
#Column(name = "cluster_uuid")
private String clusterUuid;
#Column(name = "ip", table="cluster")
private String ip;
..... }
#Entity
#Table(name = "cluster")
public class Cluster {
#Id
#Column(name = "uuid")
private String uuid;
#Column(name = "ip")
private String ip;
.....
}
Server.clusterUuid is a foreign key to Cluster.uuid. I am hoping to get Server entity that fetches ip column from Cluster by joining Server.clusterUuid to Cluster.uuid.
Then I was greeted by a hibernate exception:
Caused by: org.hibernate.AnnotationException: SecondaryTable
JoinColumn cannot reference a non primary key
at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:402)
at org.hibernate.cfg.annotations.EntityBinder.bindJoinToPersistentClass(EntityBinder.java:620)
at org.hibernate.cfg.annotations.EntityBinder.createPrimaryColumnsToSecondaryTable(EntityBinder.java:612)
I see lots of people encountered this problem. But the first bug for this in Hibernate's bugzilla was 2010, I am surprised it's been there for over two years as this is supposed to be a basic feature. There is some post saying JPA spec only allows primary key to do the mapping, however, I get below from JPA wikibook
JPA allows multiple tables to be assigned to a single class. The
#SecondaryTable and SecondaryTables annotations or
elements can be used. By default the #Id column(s) are assumed to be
in both tables, such that the secondary table's #Id column(s) are the
primary key of the table and a foreign key to the first table. If
the first table's #Id column(s) are not named the same the
#PrimaryKeyJoinColumn or can be used to
define the foreign key join condition.
it's obviously OK for non-primary key. Then I am confused why Hibernate didn't fix this problem as it seems to be easy to implement by a join clause.
anybody knows how to overcome this problem? thank you.
I don't quite understand your setup.
#SecondaryTable is for storing a single entity in multiple tables, but in your case you have a many-to-one relationship between different entities (each one stored in its own table), and it should be mapped as such:
#Entity
#Table(name="server")
public class Server {
#ManyToOne
#JoinColumn(name = "cluster_uuid")
private Cluster cluster;
...
}