This is the concerned Java code
Role.Java
#Entity
#Table(name = "role")
public class Role extends BasicModel {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id")
private int id;
#Column(name = "role_name")
private String roleName;
#OneToMany(mappedBy = "pk.role", cascade=CascadeType.ALL)
private Set<UserRoles> userRoles = new HashSet<UserRoles>();
//Getters and Setters
}
User.Java
#Entity
#Table(name = "user")
public class User extends BasicModel{
#Id
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
#Column(name = "email")
private String email;
#Column(name = "password")
private String password;
#OneToMany(mappedBy = "pk.user", cascade=CascadeType.ALL)
private Set<UserRoles> userRoles = new HashSet<UserRoles>();
//getters and setters
}
UserRoles.Java
#Entity
#Table(name = "user_roles")
#AssociationOverrides({
#AssociationOverride(name = "pk.user",
joinColumns = #JoinColumn(name = "user_id")),
#AssociationOverride(name = "pk.role",
joinColumns = #JoinColumn(name = "role_id")) })
public class UserRoles extends BasicModel {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id")
private int id;
#EmbeddedId
private UserRoleId pk = new UserRoleId();
//Getters and Setters
}
**UserRoleId.java**
public class UserRoleId {
#ManyToOne
private User user;
#ManyToOne
private Role role;
//Getters and Setters
}
This is the code I am using to insert
tx = session.beginTransaction();
User user = new User();
user.setName("admin");
user.setPassword("admin");
user.setEmail("admin#admin.com");
Role role = new Role();
role.setRoleName("admin");
session.save(role);
UserRoles userRole = new UserRoles();
userRole.setUser(user);
userRole.setRole(role);
user.getUserRoles().add(userRole);
session.save(user);
tx.commit();
In Role and User class, if I set the cascadetype as ALL like
#OneToMany(mappedBy = "pk.role", cascade=CascadeType.ALL)
private Set<UserRoles> userRoles = new HashSet<UserRoles>();
I am getting the following error
org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:72)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:190)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:62)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3124)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3581)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:104)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:349)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at com.testworks.test.dao.impl.UserDAOImpl.insertUser(UserDAOImpl.java:68)
at com.testworks.test.dao.impl.UserDAOImpl.main(UserDAOImpl.java:82)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:
Cannot add or update a child row: a foreign key constraint fails (`test`.`user_roles`, CONSTRAINT `FK_user_roles_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`))
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
at com.mysql.jdbc.Util.getInstance(Util.java:381)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3491)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3423)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1936)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2060)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2542)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1734)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2019)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1937)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1922)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:187)
... 14 more
If I set the CascadeType to other values, user table and role table gets updated and link table user_roles not getting updated.
This is the table structure in mysql
role
DROP TABLE IF EXISTS `test`.`role`;
CREATE TABLE `test`.`role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`role_name` varchar(100) DEFAULT NULL,
`created_user` varchar(45) NOT NULL,
`created_date` datetime NOT NULL,
`updated_user` varchar(45) NOT NULL,
`updated_date` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
user
DROP TABLE IF EXISTS `test`.`user`;
CREATE TABLE `test`.`user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`email` varchar(50) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL,
`created_user` varchar(45) NOT NULL,
`created_date` datetime NOT NULL,
`updated_user` varchar(45) NOT NULL,
`updated_date` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
user_roles
DROP TABLE IF EXISTS `test`.`user_roles`;
CREATE TABLE `test`.`user_roles` (
`id` int(10) NOT NULL,
`role_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`created_user` varchar(45) NOT NULL,
`created_date` datetime NOT NULL,
`updated_user` varchar(45) NOT NULL,
`updated_date` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_user_roles_user` (`user_id`),
KEY `FK_user_roles_roles` (`role_id`),
CONSTRAINT `FK_user_roles_roles` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`),
CONSTRAINT `FK_user_roles_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Please help.
I went through this link
http://developmentality.wordpress.com/2011/05/23/hibernate-mysql-mac-foreign-key-nightmares-a-painless-solution-to-a-painful-problem/
and executed this command
show engine innodb status
in mysql command line and found, the query generated like this
insert into user_roles (created_date, created_user, updated_date, updated_user, role_id, user_id, id) values ('2014-11-01 11:57:03', 'test', '2014-11-01 11:57:03', 'test', 0, 0, 0);
which is because
the value of user_id and role_id is not getting incremented.
Now I added this line
#GeneratedValue(strategy = GenerationType.IDENTITY)
to auto generate id in both user and role tables and the issue is now resolved.
Thanks !
Related
I use this entity definition for JPA:
#Entity
#Table(name = "payment_transactions")
public class PaymentTransactions implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", unique = true, updatable = false, nullable = false)
private int id;
#Column
private Date date;
#Column
private Integer year;
.....
}
Table is successfully created:
CREATE TABLE `payment_transactions` (
`id` int(11) NOT NULL,
....
PRIMARY KEY (`id`),
}
Table is successfully created.
But I would like MariaDB to auto-generate unique table key value. Like this:
CREATE TABLE `payment_transactions` (
`id` int(11) NOT NULL auto_increment,
....
PRIMARY KEY (`id`),
}
What is the proper way to configure this with JPA?
I am creating a project in spring boot which creates record by api call.
so I have two table ( name and phone ) below is my domain:
#Entity
#Table(name = "name")
public class Name {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "name", nullable = false)
private String name;
#Column(name = "active", nullable = false)
private boolean active = true;
#LazyCollection(LazyCollectionOption.FALSE)
#OneToMany(mappedBy = "name")
#JsonIgnoreProperties("name")
private List<Phone> phones;
}
And
#Entity
#Table(name = "phone")
public class Phone {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "number", nullable = false)
private String number;
#Column(name = "active", nullable = false)
private boolean active = true;
#ManyToOne(targetEntity= Name.class)
#JoinColumn(name="name_id"))
private Name name;
}
The Code to create the name is as follows:
public Name createNewName(Name createName) {
Name newName = new Name();
newName = NameRepo.save(createName);
return newName;
}
And Repository is:
#Repository
public interface NameRepository extends PagingAndSortingRepository<Name, Long> {}
So My problem is when i send a request using api to call this, Name does not store Phone values and also does not link if exist.
My request is as follows:
{
"name": "testrretf",
"active": true,
"phones":[{
"id":1
}]
}
This request should link the new Name to existing Phone id=1
And
{
"name": "testrretf",
"active": true,
"phones":[{
"number":"Test Phone",
"active":true,
}]
}
This request should create a Phone and link to the created Name.
Please help me..
Thanks,
UPDATE# Below is the Create Table Query:
CREATE TABLE `name` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`active` bit(1) NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `IDX_NAME` (`name `),
KEY `IDX_NAME_ACTIVE` (`active`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
CREATE TABLE `phone` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`active` bit(1) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`name_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `IDX_PHONE_ACTIVE` (`active`),
KEY `fk_name_phone` (`name_id`),
CONSTRAINT `fk_name_phone` FOREIGN KEY (`name_id`) REFERENCES `name` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
I have these two tables in my database:
CREATE TABLE classroom_trainee (
id BIGINT(20) NOT NULL AUTO_INCREMENT,
trainee_id BIGINT(20) NOT NULL,
classroom_id BIGINT(20) NOT NULL,
completed BOOLEAN,
notes VARCHAR(255),
result INT(3),
feedback BOOLEAN DEFAULT 0,
PRIMARY KEY (id),
FOREIGN KEY (trainee_id)
REFERENCES user (id),
FOREIGN KEY (classroom_id)
REFERENCES classroom (id)
);
CREATE TABLE trainee_presence (
id BIGINT(20) NOT NULL AUTO_INCREMENT,
classroom_trainee_id BIGINT(20) NOT NULL,
day INT(2) NOT NULL,
presence BOOLEAN,
notes VARCHAR(255),
PRIMARY KEY (id),
FOREIGN KEY (classroom_trainee_id)
REFERENCES classroom_trainee (id)
);
and this is the Entities that I have:
UserEntity.java:
....
public class UserEntity implements Serializable {
...
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "manager_id")
private UserEntity manager;
#Column(name = "email", nullable = false, unique = true)
private String email;
#Column(name = "forename")
private String forename;
#Column(name = "surname")
private String surname;
...
ClassroomTraineeEntity.java
....
public class ClassroomTraineeEntity {
.....
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#ManyToOne
#JoinColumn(name="trainee_id")
private UserEntity trainee;
#ManyToOne
#JoinColumn(name="classroom_id")
private ClassroomEntity classroom;
....
TraineePresenceEntity.java
....
public class TraineePresenceEntity {
.......
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#ManyToOne
#JoinColumn(name="classroom_trainee_id")
private ClassroomTraineeEntity classroomTrainee;
#Column(name = "day")
private Integer day;
#Column(name = "presence")
private Boolean presence;
...
When in TraineePresenceEntity I use
#Column(name="classroom_trainee_id")
private Integer classroomTraineeId;
It all works fine and dandy, but with a ClassroomTraineeEntity object I get this exception:
Caused by: org.hibernate.MappingException: Foreign key (FKn85t08ggb5n6ail459koe0sm8:trainee_presence [classroom_trainee_id])) must have same number of columns as the referenced primary key (classroom_trainee [classroom_id,trainee_id])
Anyone knows how I can solve this problem?
CREATE TABLE `incident` (
`author_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`email` varchar(45) NOT NULL,
PRIMARY KEY (`author_id`)
);
CREATE TABLE `adr` (
`author_id` int(11) NOT NULL,
`title` varchar(128) NOT NULL,
`description` varchar(512) NOT NULL,
`published` date NOT NULL,
PRIMARY KEY (`author_id`),
KEY `author_fk` (`author_id`),
CONSTRAINT `author_fk` FOREIGN KEY (`author_id`) REFERENCES `incident` (`author_id`)
);
Here its a one to one mapping between incident and adr.
In adr table, where author_id is both PK & FK.
How can we create an entity class for this king of one to one relation ship.
Tried Solution
//incident table entity class
Entity
#Table(name="INCIDENT")
public class Incident implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name="IR_TB_INCIDENT_HDR_INCIDENTID_GENERATOR", sequenceName="IR_SEQ_INCIDENT_ID")
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="IR_TB_INCIDENT_HDR_INCIDENTID_GENERATOR")
#Column(name="AUTHOR_ID")
private int authorId;
#Column(name="NAME")
private String name;
#Column(name="EMAIL")
private String email;
#OneToOne(cascade = {CascadeType.PERSIST,CascadeType.MERGE, CascadeType.REMOVE}, fetch = FetchType.LAZY, mappedBy="Incident")
private Adr adr;
/** constructors , getters & sertters **/
}
compile time Exception in Incident.java
In attribute 'adr', the "mapped by" attribute 'incident' has an invalid mapping type for this relationship.
How can I define adr entity so that author id will refer to author Id in incident table
tried this but not working
#Entity
#Table(name="ADR")
public class Adr implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name="INCIDENT_ID")
private Incident Incident;
#Column(name="TITLE")
private String title;
/** rest of the fields and methos **/
}
I have problem when i try add data to table USERS. First my DB and classes.
DB structure:
CREATE TABLE IF NOT EXISTS `admins` (
`ADMIN_ID` int(10) unsigned NOT NULL AUTO_INCREMENT ,
`USERNAME` varchar(45) NOT NULL,
`PASSWORD` varchar(45) NOT NULL,
`AUTHORITY` varchar(45) NOT NULL,
PRIMARY KEY (`ADMIN_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `lecturers` (
`LECTURER_ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`NAME` varchar(45) NOT NULL,
`SURNAME` varchar(45) NOT NULL,
`TITLES` varchar(45) NOT NULL,
`USERNAME` varchar(45) NOT NULL,
`PASSWORD` varchar(45) NOT NULL,
`AUTHORITY` varchar(45) NOT NULL,
`LEC_DESCRIPTION` varchar(100) NOT NULL,
PRIMARY KEY (`LECTURER_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=40;
CREATE TABLE IF NOT EXISTS `roles_name` (
`role_id` int(1) NOT NULL,
`authority` varchar(45) NOT NULL,
UNIQUE KEY `role_id` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `roles_name` (`role_id`, `authority`) VALUES
(1, 'ROLE_ADMIN'),
(2, 'ROLE_USER'),
(3, 'ROLE_LECTURER');
CREATE TABLE IF NOT EXISTS `users` (
`USER_ID` int(10) unsigned NOT NULL AUTO_INCREMENT ,
`NAME` varchar(45) NOT NULL,
`SURNAME` varchar(45) NOT NULL,
`username` varchar(45) NOT NULL,
`PASSWORD` varchar(45) NOT NULL,
`USER_DESCRIPTION` varchar(100) NOT NULL,
`AUTHORITY` varchar(45) NOT NULL,
`ENABLED` tinyint(1) NOT NULL,
PRIMARY KEY (`USER_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=50000;
CREATE TABLE IF NOT EXISTS `roles_map` (
`rm_id` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned,
`admin_id` int(10) unsigned,
`lecturer_id` int(10) unsigned,
`username` varchar(45) NOT NULL,
`password` varchar(45) NOT NULL,
`role_id` int(1) NOT NULL,
PRIMARY KEY (`rm_id`),
FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`),
FOREIGN KEY (`lecturer_id`) REFERENCES `lecturers` (`lecturer_id`),
FOREIGN KEY (`admin_id`) REFERENCES `admins` (`admin_id`),
FOREIGN KEY (`role_id`) REFERENCES `roles_name` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
RolesMap.java
#Entity
#Table(name = "roles_map")
public class RolesMap {
#Id
#Column(name = "RM_ID", unique = true, nullable = false)
private int rm_id;
//#Column(name = "USER_ID", unique = true)
//private int user_id;
#Column(name = "ADMIN_ID", unique = true)
private int admin_id;
#Column(name = "LECTURER_ID", unique = true)
private int lecturer_id;
#Column(name = "USERNAME", unique = true, nullable = false)
private String username;
#Column(name = "PASSWORD", unique = true, nullable = false)
private String password;
#Column(name = "ROLE_ID", unique = true, nullable = false)
private int role_id;
#ManyToOne(cascade={CascadeType.ALL})
#JoinColumn(name = "user_id")
private User user;
//getters and setters
}
User.java
#Entity
#Table(name = "users")
public class User {
#Id
#Column(name = "USER_ID", unique = true, nullable = false)
private int user_id;
#Column(name = "NAME", nullable = false)
private String name;
#Column(name = "SURNAME", unique = true, nullable = false)
private String surname;
#Column(name = "USERNAME", unique = true, nullable = false)
private String username; // zamiast username
#Column(name = "PASSWORD", unique = true, nullable = false)
private String password;
#Column(name = "USER_DESCRIPTION", nullable = false)
private String userDescription;
#Column(name = "AUTHORITY", nullable = false)
private String authority = "ROLE_USER";
#Column(name = "ENABLED", nullable = false)
private int enabled;
#OneToMany(mappedBy="user", cascade=CascadeType.ALL)
private List <RolesMap> rolesMap;
//getters and setters
}
adding method
public String addUser() {
Session sess = null;
try {
sess = UserDao.getSessionFactory().openSession();
sess.beginTransaction();
RolesMap roles = new RolesMap();
//roles.setrUser(user);
User user = new User();
roles.setPassword(getPassword());
roles.setRole_id(2);
roles.setUsername(getUsername());
user.setName(getName());
user.setSurname(getSurname());
user.setUsername(getUsername());
user.setPassword(getPassword());
user.setUserDescription(getUserDescription());
user.setAuthority(getAuthority());
user.setEnabled(getEnabled());
user.setRolesMap(new ArrayList<RolesMap>());
user.getRolesMap().add(roles);
sess.save(user);
sess.getTransaction().commit();
//getUserService().addUser(user);
return SUCCESS;
} catch (DataAccessException e) {
e.printStackTrace();
}
return ERROR;
}
When I try use this method I have error:
Cannot add or update a child row: a foreign key constraint fails (soeOne2.roles_map, CONSTRAINT roles_map_ibfk_2 FOREIGN KEY (lecturer_id) REFERENCES lecturers (LECTURER_ID))
But I do not know why, because I'm trying to add data to the USER and ROLESMAP tables. I think when you add data to a table ROLESMAP/USER field lecturer_id and admin_id in ROLESMAP table shuld be NULL. Can anyone tell me what I'm doing wrong?
It is because lecturer_id=0 is NOT lecturer_id=null.
Your application try to save lecturer_id=0 and the database think that 0 is the ID of an item in table lecturers.
So the first workarround is to replace the int with Integer, so that you can assign lecturer_id = null
#Column(name = "LECTURER_ID", unique = true)
private Integer lecturer_id;
And I think you need this modification for all other references that work the same way.
The second point is, that the way you map references between entities is not the jpa (hibernate) way. I strongly recommend that you read something about mapping relations (OneToOne, OneToMany, ManyToOne, ManyToMany) For example the Hibernate Reference Chapter 7. Collection mapping and 8. Association Mappings