アプリケーションと application_descriptions 間のマッピングを持つデータベースがあります。すべてのアプリケーションは、複数の説明を持つことができます (列 product_id によってマップされます)。テーブル アプリケーションの列 product_id は重複する値を持つことができますが、列 product_id と列ラッピング_バージョンの組み合わせは一意です。したがって、説明は、最新バージョンのアプリケーションにのみマップする必要があります。
すべての説明を取得するために、テーブル アプリケーションで @OneToMany マッピングを作成しました。説明では、product_id の文字列のみを取得します。これは最適ではありませんが、代替 a) のようにマップすることはできません。
したがって、私が作成したソリューションは、データベースからデータを読み取るためにうまく機能しましたが、アプリケーションをデータベースに更新しようとすると、次のエラーが発生します(時々のみ):
Hibernate:
/* update
com.twistbox.iwp.dao.Application */ update
applications
set
created=?,
design_id=?,
message=?,
product_id=?,
product_title=?,
retailer_id=?,
state=?,
tbyb_playduration=?,
tbyb_startups=?,
wrapping_security_layer=?,
wrapping_version=?
where
id=?
Hibernate:
/* delete one-to-many com.twistbox.iwp.dao.Application.applicationDescriptions */ update
application_descriptions
set
product_id=null
where
product_id=?
104330 [http-8080-1] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 1048, SQLState: 23000
104330 [http-8080-1] ERROR org.hibernate.util.JDBCExceptionReporter - Column 'product_id' cannot be null
1.更新する前にマップされた説明セットをnullに設定する 2.更新する前に新しい空のHashSetオブジェクトに設定する 3.マップされたオブジェクトをデータベースから取得するようにします
デフォルトでは、休止状態は更新時にカスケードされるべきではなく、停止する方法が見つかりませんでした (最後の試みは @OneToMany(cascade = {}) でした)。また、両方のテーブルで次の true 値と false 値を試しました。
それらのいくつかは、エラーが発生したアプリケーションで機能しましたが、属性を再度削除した場合にのみ機能する他のアプリケーションでも同じエラーが発生します。何をすべきか?
私のコード(重要なゲッターとセッターのみ、より良い概要のために他のすべてを削除):
@Entity
@Table (name = "applications")
@FilterDef(name = "versionFilter")
public class Application implements Comparable<Application>, Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private long id;
private Retailer retailerId;
private long designId;
private String productId;
private String productTitle;
private int tbybPlayDuration;
private int tbybStartups;
private int wrappingSecurityLayer;
private int wrappingVersion;
private ApplicationStatus status;
private String message;
private Timestamp created;
private Set<ApplicationDescription> applicationDescriptions = new HashSet<ApplicationDescription>();
private Set<PricingApplicationMapping> pricingApplication = new HashSet<PricingApplicationMapping>();
public Application() {
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@GenericGenerator(name="increment", strategy="increment")
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Column(name="product_id")
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
@OneToMany(cascade = {})
@JoinColumn(name="product_id", referencedColumnName="product_id")
@Filter(name = "versionFilter", condition = "wrapping_version =select max(A.wrapping_version) from application A where A.product_id= product_id")
public Set<ApplicationDescription> getApplicationDescriptions() {
return applicationDescriptions;
}
public void setApplicationDescriptions(
Set<ApplicationDescription> applicationDescriptions) {
this.applicationDescriptions = applicationDescriptions;
}
@Override
public int compareTo(Application o) {
return this.getProductTitle().compareToIgnoreCase(o.getProductTitle());
}
}
@Entity
@Table (name = "application_descriptions")
@FilterDef(name = "paMapping")
public class ApplicationDescription implements Comparable<ApplicationDescription>, Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private long id;
private String productId;
// private Application application;
// private String countryCode;
private Territory territory;
private String name;
private String description;
private String termsAndConditions;
public ApplicationDescription() {
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@GenericGenerator(name="increment", strategy="increment")
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
// @ManyToOne
// @JoinColumn(name="product_id")
// public Application getApplication() {
// return application;
// }
//
// public void setApplication(Application application) {
// this.application = application;
// }
@Column(name="product_id")
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
@Column(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Column(name="terms_and_conditions")
public String getTermsAndConditions() {
if (this.termsAndConditions != null && !this.termsAndConditions.equals("") && !this.termsAndConditions.toLowerCase().equals("null"))
return this.termsAndConditions;
return "default";
}
public void setTermsAndConditions(String termsAndConditions) {
this.termsAndConditions = termsAndConditions;
}
@JoinColumn(name="country_code")
@OneToOne
public Territory getTerritory() {
return territory;
}
public void setTerritory(Territory territory) {
this.territory = territory;
}
@Override
public int compareTo(ApplicationDescription o) {
return this.getTerritory().getCountryCode().compareToIgnoreCase(o.getTerritory().getCountryCode());
}
}
application_descriptions の product_id の代替 a):
@ManyToOne
@JoinColumn(name="product_id")
public Application getApplication() {
return application;
}
エラーメッセージ:
Hibernate:
/* load one-to-many com.twistbox.iwp.dao.Application.applicationDescriptions */ select
applicatio0_.product_id as product5_0_2_,
applicatio0_.id as id2_,
applicatio0_.id as id4_1_,
applicatio0_.product_id as product5_4_1_,
applicatio0_.description as descript2_4_1_,
applicatio0_.name as name4_1_,
applicatio0_.terms_and_conditions as terms4_4_1_,
applicatio0_.country_code as country6_4_1_,
territory1_.country_code as country1_8_0_,
territory1_.currency as currency8_0_,
territory1_.name as name8_0_,
territory1_.terms_and_conditions as terms4_8_0_
from
application_descriptions applicatio0_
left outer join
territories territory1_
on applicatio0_.country_code=territory1_.country_code
where
applicatio0_.product_id=?
180684 [http-8080-1] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 0, SQLState: S1009
180684 [http-8080-1] ERROR org.hibernate.util.JDBCExceptionReporter - Invalid value for getLong() - 'para'
SQL 生成テーブル:
CREATE TABLE IF NOT EXISTS `applications` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`retailer_id` int(10) unsigned NOT NULL,
`design_id` int(10) unsigned NOT NULL,
`product_id` varchar(150) NOT NULL,
`product_title` varchar(150) NOT NULL,
`tbyb_playduration` int(10) NOT NULL,
`tbyb_startups` int(10) NOT NULL,
`wrapping_security_layer` int(10) unsigned NOT NULL DEFAULT '1',
`wrapping_version` int(10) unsigned NOT NULL DEFAULT '1',
`state` enum('WAITING','RUNNING','DONE','FAILED') NOT NULL DEFAULT 'WAITING',
`message` varchar(250) DEFAULT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `product_id_wrapping_version` (`product_id`,`wrapping_version`),
KEY `FK_applications_retailers` (`retailer_id`),
KEY `FK_applications_custom_designs` (`design_id`),
KEY `product_id` (`product_id`),
CONSTRAINT `FK_applications_custom_designs` FOREIGN KEY (`design_id`) REFERENCES `custom_designs` (`id`),
CONSTRAINT `FK_applications_retailers` FOREIGN KEY (`retailer_id`) REFERENCES `retailers` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `application_descriptions` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`product_id` varchar(150) NOT NULL,
`country_code` varchar(5) NOT NULL,
`name` varchar(150) NOT NULL,
`description` varchar(500) NOT NULL,
`terms_and_conditions` text,
PRIMARY KEY (`id`),
UNIQUE KEY `product_id_county_code` (`product_id`,`country_code`),
KEY `FK_application_descriptions_applications` (`product_id`),
KEY `FK_application_descriptions_territories` (`country_code`),
CONSTRAINT `FK_application_descriptions_territories` FOREIGN KEY (`country_code`) REFERENCES `territories` (`country_code`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
アプリケーションの更新:
public static long updateApplication(Application application){
SessionFactory sf = HibernateUtil.getSessionFactory();
Session session = null;
try{
session = sf.openSession();
session.beginTransaction();
session.saveOrUpdate(application);
session.getTransaction().commit();
}
catch(HibernateException he){
logger.severe("Error updating application! " + he.getMessage() + " " + he.getStackTrace());
return -1;
}
catch(Exception e){
logger.severe("Error updating application! " + e.getMessage() + " " + e.getStackTrace());
return -1;
}
finally{
session.close();
}
return application.getId();
}