Hibernate throws DataIntegrityViolationException when trying to update object using merge method - java

Previous update() method was throwing different object with the same identifier value was already associated with the session so I changed dao to merge. Now it gives org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
TeamDAOImpl
public void updateTeam(Team team) {
Team teamToUpdate = getTeam(team.getId());
teamToUpdate.setName(team.getName());
teamToUpdate.setRating(team.getRating());
Set<TeamMember> teamMember = team.getTeamMembers();
teamToUpdate.setTeamMembers(teamMember);
getCurrentSession().merge(teamToUpdate);
}
Team entity
#Entity
#Table(name="teams")
public class Team {
private Integer id;
private String name;
private Integer rating;
private Set<TeamMember> teamMembers;
// ...
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "team_member", joinColumns =
#JoinColumn(name = "FK_Team_id", referencedColumnName= "id"),
inverseJoinColumns = #JoinColumn(name = "FK_Member_id", referencedColumnName = "id")
)
public Set<TeamMember> getTeamMembers() {
return teamMembers;
}
public void setTeamMembers(Set<TeamMember> teamMembers) {
this.teamMembers = teamMembers;
}
}
Team mas ManyToMany relationship with Team members. On SQL level it's done using tables: teams, member, team_member.
What constraints are violated? How to fix it?
UPDATE:
CREATE TABLE `member` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `teams` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`rating` int(11) NOT NULL,
`FK_Organization_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_Organization_id` (`FK_Organization_id`),
CONSTRAINT `FK_Organization_id` FOREIGN KEY (`FK_Organization_id`) REFERENCES `organization` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `team_member` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`FK_Member_id` int(11) NOT NULL,
`FK_Team_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `FK_Member_id` FOREIGN KEY (`id`) REFERENCES `member` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_Team_id` FOREIGN KEY (`id`) REFERENCES `teams` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ERROR o.h.e.jdbc.spi.SqlExceptionHelper - Cannot add or update a child
row: a foreign key constraint fails (db.team_member,
CONSTRAINT FK_Member_id FOREIGN KEY (id) REFERENCES member
(id) ON DELETE NO ACTION ON UPDATE NO ACTION)
Data:
UPDATE3
public Team getTeam(int id) {
Team team = (Team) getCurrentSession().get(Team.class, id);
return team;
}
UPDATE4
P6Spy helped to discover error query:
insert into team_member (FK_Team_id, FK_Member_id) values (2, 2);
returning:
[SQL] insert into team_member (FK_Team_id, FK_Member_id) values (2, 2);
[Err] 1452 - Cannot add or update a child row: a foreign key constraint fails (`db`.`team_member`, CONSTRAINT `FK_Member_id` FOREIGN KEY (`id`) REFERENCES `member` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION)

Problem was in CONSTRAINT definition in team_member table. Instead of:
CONSTRAINT `FK_Member_id` FOREIGN KEY (`id`) REFERENCES `member` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_Team_id` FOREIGN KEY (`id`) REFERENCES `teams` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
It has to be
CONSTRAINT `FK_Member_id` FOREIGN KEY (`FK_Member_id`) REFERENCES `member` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_Team_id` FOREIGN KEY (`FK_Team_id`) REFERENCES `teams` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION

Related

Join column from another table with Foreign Key using JPA

I'm new to JPA and trying to understand if there's a way to make an Entity where one column is coming from another table that is linked by a foreign key. For example, consider the following tables:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `jobs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11),
PRIMARY KEY (`id`),
CONSTRAINT `fk_jobs_users` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
);
Now I want to make an Entity for the "jobs" table that will include the user.email. I know I can do something like
#Entity
#Table(name = "jobs")
public class JobEntity {
#Id
#Column(name = "id")
private Long id;
#Column(name = "user_id")
private Long userId;
#Formula("(select user.email FROM user WHERE user.id = user_id)")
private String userEmail;
But I feel there's a way I can better leverage the foreign key relationship, but I'm not sure how. I was looking into #JoinColumn but was not seeing the result I wanted since the foreign key is a different column in my Entity. Is there a better way rather than using #Forula to do this?
I don't really understand this. I'm sure #JoinColumn can accomplish the behavior you're looking for.
I was looking into #JoinColumn but was not seeing the result I wanted since the foreign key is a different column in my Entity
Example:
#Entity
#Table(name = "jobs")
public class KronosFileEntity {
#Id
#Column(name = "id")
private Long id;
#ManyToOne
#JoinColumn(name = "user_id", referencedColumn = "id")
private User user;
}
Then you can access the email like job.getUser().getEmail()
Or add a convenience method if that helps
public String getUserEmail() {
return user.getEmail();
}
Then
job.getUserEmail()

Creating custom query in spring

How to create custom query in spring for getting all user who follow me from database..this is my repository
#Repository
public interface FollowRepository extends JpaRepository<Follow, Long> {
#Query("Select f from Follow f where f.user = :user and f.status = 'follow'")
List<Follow> findByUser (#Param("user") User user);
}
and this is my table in database
CREATE TABLE IF NOT EXISTS `follow`(
`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`user_id` BIGINT,
`follower_id` BIGINT,
`status` ENUM ('follow','blocked') NOT NULL,
FOREIGN KEY (user_id) REFERENCES `user`(id),
FOREIGN KEY (follower_id) REFERENCES `user`(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
#Query("Select f from Follow f where f.userId = ?1 and f.status = ?2")
List<Follow> findByUser (Integer userId, String status);
You could also:
List<Follow> findByUserAndStatus(User user, String status);
EDIT: Having your status as an ENUM in your table can make it stressful when making new enums. I'd prefer having the status column as a VARCHAR and in your entity your getter for that field can be:
#Basic
#Column(name = "status")
#Enumerated(EnumType.STRING)
public StatusEnum getStatus(){ return this.getStatus; }

Field 'ID' doesn't have a default value

I am using MySQL with Hibernate and JPA2.
I have the following table, which I would expect to auto generate the ID because AI (Auto Increment) is checked:
CREATE TABLE `job` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`JOINING_DATE` double NOT NULL,
`LASTACCESS_DATE` double NOT NULL,
`PHONE_NUMBER` varchar(55) DEFAULT NULL,
`MOBILE_NUMBER` varchar(55) DEFAULT NULL,
`EMAIL_ADDRESS` varchar(55) DEFAULT NULL,
`SEX` int(1) DEFAULT NULL,
`JOB_TITLE` varchar(65) NOT NULL,
`JOB_DESCRIPTION` varchar(800) NOT NULL,
`JOB_DETAILS` varchar(800) DEFAULT NULL,
`DRIVERS_LICENCE` int(1) DEFAULT NULL,
`AVATAR` longblob,
`TYPE` int(1) NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `ID_UNIQUE` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=87 DEFAULT CHARSET=utf8;
Job.java
#Entity
#Table(name = "job")
#XmlRootElement(name = "job")
public class Job extends AbstractDomain<Long> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...
Dao.java
protected T merge(T entity) throws InstantiationException, IllegalAccessException {
T attached = null;
if (entity.getId() != null) {
attached = entityManager.find(entityClass, entity.getId());
}
if (attached == null) {
attached = entityClass.newInstance(); // <= this is executed
}
BeanUtils.copyProperties(entity, attached);
entityManager.merge(attached); // <= ID is null here
return attached;
}
When I try merge the table, I get the following error:
Caused by: java.sql.SQLException: Field 'ID' doesn't have a default value
Strange thing is this was working earlier, and the Java code has not changed, I did make changes to some other database tables only. I have read here that some people had this problem and fixed it by dropping and importing their database. I did drop the schema and imported it again. But still get the same error.
Does anyone have any ideas please?

Can I create an #ElementCollection of #Entity?

I'm trying to find relevant JPA documentation, but having trouble finding anything that specifies if I am allowed to make an ElementCollection of an Entity. I know the typical use is to make an #ElementCollection of #Embeddable, but due to a Hibernate bug I encountered, I need to make my embeddable class into its own entity.
I would like to maintain the entity's lifecycle to be controlled by the parent class. Consequently, I am hoping not to create any DAO/Repository for the new entity.
Although Hibernate allows this to occur (it properly generates the DDL), I have not actually tested persistence of the parent entity yet.
Additionally, I have not been able to find any way to specify the join column mapping to the new entity.
For example, given:
public class User {
#TableGenerator( name="UUIDGenerator", pkColumnValue="user_id", table="uuid_generator", allocationSize=1)
#Id
#GeneratedValue(strategy = GenerationType.TABLE, generator="UUIDGenerator")
#Column(name = "id")
private Long id;
/**
* Address
*/
#Valid
#ElementCollection(fetch=FetchType.LAZY)
#CollectionTable(name="user_address", joinColumns=#JoinColumn(name = "user_id", referencedColumnName = "id"))
#OrderColumn
private List<Address> address;
}
and
#Entity
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
/**
* Multiple street lines allowable
*/
#NotBlank
#ElementCollection(targetClass=String.class, fetch=FetchType.LAZY)
#CollectionTable( joinColumns=#JoinColumn(name = "address_id", referencedColumnName = "id"))
#OrderColumn
private List<String> street;
}
it generates the following MySQL tables:
CREATE TABLE `user` (
`id` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `user_address` (
`user_id` bigint(20) NOT NULL,
`address` bigint(20) NOT NULL,
`address_order` int(11) NOT NULL,
PRIMARY KEY (`user_id`,`address_order`),
UNIQUE KEY `UK_m09f5sbmw3q9drll2qig9i07q` (`address`),
KEY `FK_m09f5sbmw3q9drll2qig9i07q` (`address`),
KEY `FK_kfu0161nvirkey6fwd6orucv7` (`user_id`),
CONSTRAINT `FK_kfu0161nvirkey6fwd6orucv7` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
CONSTRAINT `FK_m09f5sbmw3q9drll2qig9i07q` FOREIGN KEY (`address`) REFERENCES `address` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `address` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `address_street` (
`address_id` bigint(20) NOT NULL,
`street` varchar(255) DEFAULT NULL,
`street_order` int(11) NOT NULL,
PRIMARY KEY (`address_id`,`street_order`),
KEY `FK_jrcnrclixxqroefuqc7gjhoh` (`address_id`),
CONSTRAINT `FK_jrcnrclixxqroefuqc7gjhoh` FOREIGN KEY (`address_id`) REFERENCES `address` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I'd like to find a way to change the field name for user_address.address. So far, the only way I can figure out how to do this is to make it a #OneToMany mapping and use a #JoinTable() definition. Is there no way from within #ElementCollection?
You cannot have an ElementCollection containing Entities, these are mutually exclusive concepts in JPA.
You can try a one-to-many or many-to-many depending on your needs. If you set fetching to eager and cascade all it should be fine.

OpenJPA Mysql always getting id null

I'm trying to run a simple example which is just a mapping with a table and to print all the values stored in it.
I'm getting all my fields well except my id.
Here is my table when i do an export on it
CREATE TABLE `adress` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`streetNumber` tinyint(4) DEFAULT NULL,
`street` varchar(45) DEFAULT NULL,
`city` varchar(45) DEFAULT NULL,
`zipCode` int(11) DEFAULT NULL,
`state` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
LOCK TABLES `adress` WRITE;
INSERT INTO `adress` VALUES (1,12,'Canada street','LOS ANGELES',441233,'California'),(2,54,'5th avenue','NEW YORK CITY',884769,'New York');
UNLOCK TABLES;
My Entity class :
#Entity
#Table(name = "adress")
#XmlRootElement
public class Adress implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Column(name = "streetNumber")
private Short streetNumber;
...
If i do a "findAll()" i'm able to get all my datas from the db.
But the id is null, all the other fields have their values
I have tried several stuff but i'm not going everywhere.
If someone can see where or about what is my mistake i'll appreciate a lot your help.
Thanks in advance

Categories

Resources