我有一个在应用程序和 application_descriptions 之间映射的数据库。每个应用程序可以有多个描述(由列 product_id 映射)。表应用中的product_id 列可以有重复值,但是product_id 列和wrapping_version 列的组合是唯一的。所以描述应该只映射到最高版本的应用程序。
我已经在表应用程序中制定了一个 @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 值:1. 属性可以为空 2. 可更新 3. 可插入
其中一些适用于我收到错误的应用程序,但随后我收到其他应用程序的相同错误,只有当我再次删除属性时才有效。有什么想法该怎么做?
我的代码(只有重要的 getter 和 setter,所有其他的都被删除以获得更好的概览):
@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 a) 中 product_id 的替代方案:
@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();
}