使用されているテクノロジー: Spring MVC 、Hibernate 、MySQL DB、Windows 7、NetBeans IDE
私の作成、読み取り、更新操作は機能しますが、ユーザーアカウントと関連するパスワードレコードを削除しようとすると例外が発生します:
SEVERE: 親行を削除または更新できません: 外部キー制約が失敗します ( profiler
. password
, CONSTRAINT FK4C641EBBCF6D23F4
FOREIGN KEY ( user_id
) REFERENCES user_account
( user_id
)) 2012 年 10 月 10 日 11:52:22 AM org.hibernate.event.def.AbstractFlushingEventListener performExecutions SEVERE: Couldデータベースの状態をセッション org.hibernate.exception.ConstraintViolationException と同期しません: JDBC バッチ更新を実行できませんでした
原因: java.sql.BatchUpdateException: 親行を削除または更新できません: 外部キー制約が失敗しました ( profiler
. password
, CONSTRAINT FK4C641EBBCF6D23F4
FOREIGN KEY ( user_id
) REFERENCES user_account
( user_id
))
ユーザーアカウントとパスワードの関係:
ユーザー アカウント クラス:
package com.profile.beans;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import javax.persistence.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@Entity
@Table(name = "user_account")
public class UserAccount implements Serializable {
@Autowired
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "user_account_seq")
@SequenceGenerator(name = "user_account_seq", sequenceName = "user_account_seq")
@Column(name = "user_id")
private Long userId ;
//
@Autowired
@Column(name = "user_name")
private String userName;
//
@Autowired
@Column(name = "user_type")
private String userType;
//
@Autowired
@Column(name = "first_name")
private String firstName;
//
@Autowired
@Column(name = "last_name")
private String lastName;
//
@Autowired
@Column(name = "email")
private String email;
//
@Autowired
@Column(name = "phone_contact")
private String phoneContact;
//
@Autowired
@Column(name = "address")
private String address;
//
@Autowired
@Column(name = "city")
private String city ;
//
@Autowired
@Column(name = "state")
private String state;
//
@Autowired
@Column(name = "country")
private String country;
//
@Autowired
@Column(name = "zipcode")
private Integer zipcode = 0;
//is the user account Active either due to user deactivation,admin deactivation, or nonpayment
@Autowired
@Column(name = "active")
private boolean active = false;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "UserAccount")
@JoinColumn(name="user_id")
private Password Password = null;
@OneToMany(mappedBy="UserAccount",cascade={CascadeType.ALL})
@JoinColumn(name="doc_id")
private List<Document> documents = null;
@Autowired(required = false)
public UserAccount() {
}
@Autowired(required = true)
public UserAccount(Long userId, String userName, String userType, String firstName, String lastName, String email, String phoneContact, String address, String city, String state, String country, Integer zipcode) {
this.userId = userId;
this.userName = userName;
this.userType = userType;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.phoneContact = phoneContact;
this.address = address;
this.city = city;
this.state = state;
this.country = country;
this.zipcode = zipcode;
}
public com.profile.beans.Password getPassword() {
return Password;
}
public void setPassword(com.profile.beans.Password Password) {
this.Password = Password;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Document> getDocuments() {
return documents;
}
public void setDocuments(List<Document> documents) {
this.documents = documents;
}
public Integer getZipcode() {
return zipcode;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getPhoneContact() {
return phoneContact;
}
public void setPhoneContact(String phoneContact) {
this.phoneContact = phoneContact;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
public void setZipcode(Integer zipcode) {
try
{
this.zipcode = zipcode;
}
catch (NumberFormatException exc)
{
exc.printStackTrace();
}
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final UserAccount other = (UserAccount) obj;
if ((this.userId == null) ? (other.userId != null) : !this.userId.equals(other.userId)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 3;
hash = 73 * hash + (this.userId != null ? this.userId.hashCode() : 0);
return hash;
}
@Override
public String toString() {
return "UserAccount{" + "userId=" + userId + ", userName=" + userName + ", userType=" + userType + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + ", phoneContact=" + phoneContact + ", address=" + address + ", city=" + city + ", state=" + state + ", country=" + country + ", zipcode=" + zipcode + ", active=" + active + ", documents=" + documents + '}';
}
}
パスワードクラス:
package com.profile.beans;
import java.io.Serializable;
import javax.persistence.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.hibernate.annotations.Cascade;
@Entity
@Table(name = "Password")
public class Password implements Serializable {
@Autowired(required = false)
public Password() {
}
@Autowired(required = true)
public Password(UserAccount UserAccount) {
this.UserAccount = UserAccount;
}
@Autowired
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "password_seq")
@SequenceGenerator(name = "password_seq", sequenceName = "password_seq")
@Column(name = "password_id")
private Long passwordId;
@Autowired
@Column(name = "password")
private String password = null;
//1 to 1 relation with UserAccounts
//1 to 1 relation with UserAccounts
@Autowired
@Qualifier("UserAccount")
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id", referencedColumnName="user_id",nullable = false)
private UserAccount UserAccount;
@Autowired(required = true)
public Password(UserAccount UserAccount, String password) {
this.UserAccount = UserAccount;
this.password = password;
}
public UserAccount getUserAccount() {
return UserAccount;
}
public void setUserAccount(UserAccount UserAccount) {
this.UserAccount = UserAccount;
}
public Long getPasswordId() {
return passwordId;
}
public void setPasswordId(Long passwordId) {
this.passwordId = passwordId;
}
public String getPassword() {
return password;
}
}
私のデータベース DDL (MySQL 構文):
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
DROP SCHEMA IF EXISTS `profiler`;
CREATE SCHEMA IF NOT EXISTS `profiler` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
DROP SCHEMA IF EXISTS `profiler` ;
CREATE SCHEMA IF NOT EXISTS `profiler` DEFAULT CHARACTER SET latin1 ;
USE `profiler` ;
-- -----------------------------------------------------
-- Table `profiler`.`user_account`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `profiler`.`user_account` ;
CREATE TABLE IF NOT EXISTS `profiler`.`user_account` (
`user_id` BIGINT(20) NOT NULL ,
`user_name` VARCHAR(45) NULL DEFAULT NULL ,
`user_type` VARCHAR(45) NULL DEFAULT NULL ,
`first_name` VARCHAR(45) NULL DEFAULT NULL ,
`last_name` VARCHAR(45) NULL DEFAULT NULL ,
`email` VARCHAR(45) NULL DEFAULT NULL ,
`phone_contact` VARCHAR(45) NULL DEFAULT NULL ,
`address` VARCHAR(45) NULL DEFAULT NULL ,
`city` VARCHAR(45) NULL DEFAULT NULL ,
`state` VARCHAR(45) NULL DEFAULT NULL ,
`country` VARCHAR(45) NULL DEFAULT NULL ,
`zipcode` VARCHAR(45) NULL DEFAULT NULL ,
`active` TINYINT(1) NULL DEFAULT NULL ,
PRIMARY KEY (`user_id`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `profiler`.`document`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `profiler`.`document` ;
CREATE TABLE IF NOT EXISTS `profiler`.`document` (
`doc_id` BIGINT(20) NOT NULL ,
`title` VARCHAR(45) NULL DEFAULT NULL ,
`format` VARCHAR(45) NULL DEFAULT NULL ,
`url_string` VARCHAR(45) NULL DEFAULT NULL ,
`size_in_bytes` INT(11) NULL DEFAULT NULL ,
`created_on` TIMESTAMP NULL DEFAULT NULL ,
`bytes` BLOB NULL DEFAULT NULL ,
`height` INT(11) NULL DEFAULT NULL ,
`width` INT(11) NULL DEFAULT NULL ,
`user_id` BIGINT(20) NOT NULL ,
PRIMARY KEY (`doc_id`) ,
CONSTRAINT `user_id_fk`
FOREIGN KEY (`user_id` )
REFERENCES `profiler`.`user_account` (`user_id` )
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `profiler`.`password`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `profiler`.`password` ;
CREATE TABLE IF NOT EXISTS `profiler`.`password` (
`password_id` BIGINT(20) NOT NULL ,
`password` VARCHAR(45) NOT NULL ,
`user_id` BIGINT(20) NOT NULL ,
PRIMARY KEY (`password_id`) ,
CONSTRAINT `user_id_fk_1`
FOREIGN KEY (`user_id` )
REFERENCES `profiler`.`user_account` (`user_id` )
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
CREATE INDEX `user_id_fk_idx` ON `profiler`.`password` (`user_id` ASC) ;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
SET foreign_key_checks = 1;
UserAccount コントローラ クラス:
@Controller
@RequestMapping("/UserAccount")
public class UserAccountController {
@Autowired
private UserAccountDao userAccountDao;
@Autowired
private PasswordDao passwordDao;
public UserAccountController() {
}
public UserAccountController(UserAccountDao userAccountDao, PasswordDao passwordDao) {
this.userAccountDao = userAccountDao;
this.passwordDao = passwordDao;
}
@RequestMapping(value="/Register")
public String RegisterationView()
{
return "UserAccount/Register";
}
@RequestMapping(value="/Login")
public String LoginView()
{
return "UserAccount/Login";
}
@RequestMapping(value="/Update")
public String UpdateView()
{
return "UserAccount/Update";
}
//create
@RequestMapping(value="/create",method = RequestMethod.POST)
public String create(
@RequestParam("username") String username,
@RequestParam("email") String email,
@RequestParam("firstname") String firstName,
@RequestParam("lastname") String lastName,
@RequestParam("phonecontact") String phonecontact,
@RequestParam("address") String address,
@RequestParam("state") String state,
@RequestParam("city") String city,
@RequestParam("country") String country,
@RequestParam("password") String password,
@RequestParam("zipcode") Integer zipcode,
HttpSession session,HttpServletRequest request, Model model)
{
String view = null ;
//*check if username exists
//*if email exists
UserAccount userAccount = new UserAccount();
userAccount.setAddress(address);
userAccount.setCity(city);
userAccount.setCountry(country);
userAccount.setState(state);
userAccount.setPhoneContact(phonecontact);
userAccount.setEmail(email);
userAccount.setZipcode(zipcode);
userAccount.setFirstName(firstName);
userAccount.setLastName(lastName);
userAccount.setUserName(username);
userAccount.setUserType(utility.UserTypes.REGULAR);
//instatiate password
//**password not exist before & must be at least characters long
Password userPassword = new Password(userAccount,password);
userAccountDao.create(userAccount);
passwordDao.create(userPassword);
//add userAccount to model
model.addAttribute("userAccount", userAccount);
session.setAttribute("userAccount", userAccount);
view = "UserAccount/UserMainMenu";
return view;
}
//update
@RequestMapping(value="/update",method = RequestMethod.GET)
public String update( @RequestParam(value="username", required=false) String username,
@RequestParam(value="email",required=false) String email,
@RequestParam(value="firstname",required=false) String firstName,
@RequestParam(value="lastname",required=false) String lastName,
@RequestParam(value="phonecontact",required=false) String phonecontact,
@RequestParam(value="address",required=false) String address,
@RequestParam(value="state",required=false) String state,
@RequestParam(value="city",required=false) String city,
@RequestParam(value="country",required=false) String country,
@RequestParam(value="zipcode",required=false) Integer zipcode,@RequestParam(value="update",required=false) String update,HttpSession session,HttpServletRequest request)
{
String view = null ;
UserAccount userAccount = (UserAccount)session.getAttribute("userAccount");
//*check if username exists
//*if email exists
try
{
System.out.println("Class UserAccountController, update:" + update);
if (update.equalsIgnoreCase("update"))
{
//reset values in case updated info
userAccount.setAddress(address);
userAccount.setCity(city);
userAccount.setCountry(country);
userAccount.setState(state);
userAccount.setPhoneContact(phonecontact);
userAccount.setEmail(email);
userAccount.setZipcode(zipcode);
userAccount.setFirstName(firstName);
userAccount.setLastName(lastName);
userAccount.setUserName(username);
userAccount.setUserType(utility.UserTypes.REGULAR);
//instatiate password
userAccountDao.update(userAccount);
//add userAccount to model
session.setAttribute("userAccount", userAccount);
view = "UserAccount/UserMainMenu";
}
if (update.equalsIgnoreCase("delete"))
{
System.out.println("Class UserAccountController, userAccount: "+userAccount);
//query for password that corresponds to particular user
Password password = (Password)passwordDao.getByUserAccount(userAccount);
System.out.println("Class UserAccountController, password: "+password );
password.setUserAccount(null);
//delete password
passwordDao.delete(password);
//delete user account
userAccountDao.delete(userAccount);
session.removeAttribute("userAccount");
view = "UserAccount/UserMainMenu";
}
}
catch (Exception exc)
{
//forward to error page
exc.getMessage();
view = "error";
}
return view;
}
//delete
@RequestMapping(value="/delete",method = RequestMethod.DELETE)
public String delete( @RequestParam("id")Long id,HttpSession session,HttpServletRequest request)
{
String view = null ;
UserAccount newUserAccount = userAccountDao.getById(id);
userAccountDao.delete(newUserAccount);
view = "UserAccount/UserMainMenu";
return view;
}
//read
@RequestMapping(value="/read",method = RequestMethod.GET)
public void read(Long id)
{
userAccountDao.getById(id);
}
public UserAccountDao getUserAccountDao() {
return userAccountDao;
}
public void setUserAccountDao(UserAccountDao userAccountDao) {
this.userAccountDao = userAccountDao;
}
public PasswordDao getPasswordDaoImpl() {
return passwordDao;
}
public void setPasswordDaoImpl(PasswordDaoImpl passwordDao) {
this.passwordDao = passwordDao;
}
}
PasswordDaoImpl クラス:
@Repository
@Transactional
public class PasswordDaoImpl implements PasswordDao{
@Autowired
private SessionFactory sessionFactory;
private Session currentSession()
{
return sessionFactory.getCurrentSession();
}
@Override
public Password getByUserAccount(UserAccount UserAccount) {
String hql = "FROM com.profile.beans.Password WHERE Password.UserAccount.UserId =:id";
Long id = UserAccount.getUserId();
Query q = currentSession().createQuery(hql);
return (Password)q.setParameter("id",id).list().get(0);
}
@Override
public void create(Password Password) {
currentSession().save(Password);
}
@Override
public void delete(Password Password) {
currentSession().delete(Password);
}
@Override
public void update(Password Password) {
currentSession().update(Password);
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}