简体   繁体   English

带有OpenJPA实体和联结表的Spring JPA映射(多对多)

[英]Spring JPA mapping with OpenJPA entities with junction table (many-to-many)

I'm having issues mapping JPA entities that are joined by a junction table. 我在映射由联结表联接的JPA实体时遇到问题。 The entities were created through STS 3.4.0 using an OpenJPA 2.3.0 implementation (Spring 4.0.2, Spring data jpa 1.5.0). 使用OpenJPA 2.3.0实现(Spring 4.0.2,Spring data jpa 1.5.0)通过STS 3.4.0创建实体。 It does appear to be doing the database hits and returning the data, but has an issue serializing the data into the JPA entities. 它似乎确实在执行数据库命中并返回数据,但是在将数据序列化为JPA实体时存在问题。 Entities are generated "Eager" using field access. 实体是使用字段访问“渴望”生成的。

Repository: 库:

interface MenuItemRepository extends JpaRepository<MlMenuItem, Short>

Calling repository.findAll(); 调用repository.findAll(); (actually happens with any add/get) I get the following error: (实际上发生在任何添加/获取中)我得到以下错误:

org.springframework.orm.jpa.JpaSystemException: org.apache.openjpa.util.ShortId cannot be cast to com.xxxxxxxxx.jpa.model.cafe.MlMenuItem org.springframework.orm.jpa.JpaSystemException:org.apache.openjpa.util.ShortId无法转换为com.xxxxxxxxx.jpa.model.cafe.MlMenuItem

It works fine if I generate the beans "lazy" and never access the items joined to it (aka. foodItems). 如果我生成“惰性” bean,并且从不访问与其关联的项(也就是foodItems),则它的工作原理很好。 If it helps, I'm very new to JPA, so may be something obvious, but non-joined tables work fine, so not sure on this one. 如果有帮助,我对JPA还是很陌生,所以可能很明显,但是非联接表可以正常工作,因此不确定对此表。

The following are the JPA entities and configuration: 以下是JPA实体和配置:

First Entity: 第一实体:

@Entity
@Table
(name="ML_MENU_ITEM")
@NamedQuery
(name="MlMenuItem.findAll", query="SELECT m FROM MlMenuItem m")
public class MlMenuItem implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="MENU_ITEM_NBR", unique=true, nullable=false)
private short menuItemNbr;
@Column(name="COMPLETED_IND", nullable=false, length=1)
private String completedInd;
@Column(name="MARKET_PRICE_IND", nullable=false, length=1)
private String marketPriceInd;
@Column(name="MENU_ITEM_DES", nullable=false, length=100)
private String menuItemDes;
@Column(name="MENU_ITEM_NAME", nullable=false, length=40)
private String menuItemName;
@OneToMany(mappedBy="mlMenuItem", fetch=FetchType.EAGER)
private List<MlMenuFoodItem> mlMenuFoodItems;
@ManyToOne
@JoinColumn(name="MENU_TYPE_CD")
private MlMenuType mlMenuType;
@ManyToOne
@JoinColumn(name="MENU_ITEM_CLS_CD", nullable=false)
private MlMnuItmClsTyp mlMnuItmClsTyp;
@OneToMany(mappedBy="mlMenuItem", fetch=FetchType.EAGER)
private List<MlMenuItemPrice> mlMenuItemPrices;
@OneToMany(mappedBy="mlMenuItem", fetch=FetchType.EAGER)
private List<MlOrdMnuItm> mlOrdMnuItms;
public MlMenuItem() {
}
public short getMenuItemNbr() {
return this.menuItemNbr;
}
public void setMenuItemNbr(short menuItemNbr) {
this.menuItemNbr = menuItemNbr;
}
public String getCompletedInd() {
return this.completedInd;
}
public void setCompletedInd(String completedInd) {
this.completedInd = completedInd;
}
public String getMarketPriceInd() {
return this.marketPriceInd;
}
public void setMarketPriceInd(String marketPriceInd) {
this.marketPriceInd = marketPriceInd;
}
public String getMenuItemDes() {
return this.menuItemDes;
}
public void setMenuItemDes(String menuItemDes) {
this.menuItemDes = menuItemDes;
}
public String getMenuItemName() {
return this.menuItemName;
}
public void setMenuItemName(String menuItemName) {
this.menuItemName = menuItemName;
}
public List<MlMenuFoodItem> getMlMenuFoodItems() {
return this.mlMenuFoodItems;
}
public void setMlMenuFoodItems(List<MlMenuFoodItem> mlMenuFoodItems) {
this.mlMenuFoodItems = mlMenuFoodItems;
}
public MlMenuFoodItem addMlMenuFoodItem(MlMenuFoodItem mlMenuFoodItem) {
getMlMenuFoodItems().add(mlMenuFoodItem);
mlMenuFoodItem.setMlMenuItem(
this);
return mlMenuFoodItem;
}
public MlMenuFoodItem removeMlMenuFoodItem(MlMenuFoodItem mlMenuFoodItem) {
getMlMenuFoodItems().remove(mlMenuFoodItem);
mlMenuFoodItem.setMlMenuItem(
null);
return mlMenuFoodItem;
}
public MlMenuType getMlMenuType() {
return this.mlMenuType;
}
public void setMlMenuType(MlMenuType mlMenuType) {
this.mlMenuType = mlMenuType;
}
public MlMnuItmClsTyp getMlMnuItmClsTyp() {
return this.mlMnuItmClsTyp;
}
public void setMlMnuItmClsTyp(MlMnuItmClsTyp mlMnuItmClsTyp) {
this.mlMnuItmClsTyp = mlMnuItmClsTyp;
}
public List<MlMenuItemPrice> getMlMenuItemPrices() {
return this.mlMenuItemPrices;
}
public void setMlMenuItemPrices(List<MlMenuItemPrice> mlMenuItemPrices) {
this.mlMenuItemPrices = mlMenuItemPrices;
}
public MlMenuItemPrice addMlMenuItemPrice(MlMenuItemPrice mlMenuItemPrice) {
getMlMenuItemPrices().add(mlMenuItemPrice);
mlMenuItemPrice.setMlMenuItem(
this);
return mlMenuItemPrice;
}
public MlMenuItemPrice removeMlMenuItemPrice(MlMenuItemPrice mlMenuItemPrice) {
getMlMenuItemPrices().remove(mlMenuItemPrice);
mlMenuItemPrice.setMlMenuItem(
null);
return mlMenuItemPrice;
}
public List<MlOrdMnuItm> getMlOrdMnuItms() {
return this.mlOrdMnuItms;
}
public void setMlOrdMnuItms(List<MlOrdMnuItm> mlOrdMnuItms) {
this.mlOrdMnuItms = mlOrdMnuItms;
}
public MlOrdMnuItm addMlOrdMnuItm(MlOrdMnuItm mlOrdMnuItm) {
getMlOrdMnuItms().add(mlOrdMnuItm);
mlOrdMnuItm.setMlMenuItem(
this);
return mlOrdMnuItm;
}
public MlOrdMnuItm removeMlOrdMnuItm(MlOrdMnuItm mlOrdMnuItm) {
getMlOrdMnuItms().remove(mlOrdMnuItm);
mlOrdMnuItm.setMlMenuItem(
null);
return mlOrdMnuItm;
}
}

Second Entity: 第二实体:

@Entity
@Table
(name="ML_FOOD_ITEM")
@NamedQuery
(name="MlFoodItem.findAll", query="SELECT m FROM MlFoodItem m")
public class MlFoodItem implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name="FOOD_ITEM_NBR", unique=true, nullable=false)
private short foodItemNbr;
@Column(name="COMPLETED_IND", nullable=false, length=1)
private String completedInd;
@Column(name="FOOD_ITEM_NAME", nullable=false, length=30)
private String foodItemName;
@Column(name="PURCHASED_IND", nullable=false, length=1)
private String purchasedInd;
@ManyToOne
@JoinColumn(name="UNIT_MEASURE_CD", nullable=false)
private MlUnitOfMeasure mlUnitOfMeasure;
@OneToMany(mappedBy="mlFoodItem1", fetch=FetchType.EAGER)
private List<MlFoodItemIngr> mlFoodItemIngrs1;
@OneToMany(mappedBy="mlFoodItem2", fetch=FetchType.EAGER)
private List<MlFoodItemIngr> mlFoodItemIngrs2;
@OneToMany(mappedBy="mlFoodItem", fetch=FetchType.EAGER)
private List<MlMenuFoodItem> mlMenuFoodItems;
public MlFoodItem() {
}
public short getFoodItemNbr() {
return this.foodItemNbr;
}
public void setFoodItemNbr(short foodItemNbr) {
this.foodItemNbr = foodItemNbr;
}
public String getCompletedInd() {
return this.completedInd;
}
public void setCompletedInd(String completedInd) {
this.completedInd = completedInd;
}
public String getFoodItemName() {
return this.foodItemName;
}
public void setFoodItemName(String foodItemName) {
this.foodItemName = foodItemName;
}
public String getPurchasedInd() {
return this.purchasedInd;
}
public void setPurchasedInd(String purchasedInd) {
this.purchasedInd = purchasedInd;
}
public MlUnitOfMeasure getMlUnitOfMeasure() {
return this.mlUnitOfMeasure;
}
public void setMlUnitOfMeasure(MlUnitOfMeasure mlUnitOfMeasure) {
this.mlUnitOfMeasure = mlUnitOfMeasure;
}
public List<MlFoodItemIngr> getMlFoodItemIngrs1() {
return this.mlFoodItemIngrs1;
}
public void setMlFoodItemIngrs1(List<MlFoodItemIngr> mlFoodItemIngrs1) {
this.mlFoodItemIngrs1 = mlFoodItemIngrs1;
}
public MlFoodItemIngr addMlFoodItemIngrs1(MlFoodItemIngr mlFoodItemIngrs1) {
getMlFoodItemIngrs1().add(mlFoodItemIngrs1);
mlFoodItemIngrs1.setMlFoodItem1(
this);
return mlFoodItemIngrs1;
}
public MlFoodItemIngr removeMlFoodItemIngrs1(MlFoodItemIngr mlFoodItemIngrs1) {
getMlFoodItemIngrs1().remove(mlFoodItemIngrs1);
mlFoodItemIngrs1.setMlFoodItem1(
null);
return mlFoodItemIngrs1;
}
public List<MlFoodItemIngr> getMlFoodItemIngrs2() {
return this.mlFoodItemIngrs2;
}
public void setMlFoodItemIngrs2(List<MlFoodItemIngr> mlFoodItemIngrs2) {
this.mlFoodItemIngrs2 = mlFoodItemIngrs2;
}
public MlFoodItemIngr addMlFoodItemIngrs2(MlFoodItemIngr mlFoodItemIngrs2) {
getMlFoodItemIngrs2().add(mlFoodItemIngrs2);
mlFoodItemIngrs2.setMlFoodItem2(
this);
return mlFoodItemIngrs2;
}
public MlFoodItemIngr removeMlFoodItemIngrs2(MlFoodItemIngr mlFoodItemIngrs2) {
getMlFoodItemIngrs2().remove(mlFoodItemIngrs2);
mlFoodItemIngrs2.setMlFoodItem2(
null);
return mlFoodItemIngrs2;
}
public List<MlMenuFoodItem> getMlMenuFoodItems() {
return this.mlMenuFoodItems;
}
public void setMlMenuFoodItems(List<MlMenuFoodItem> mlMenuFoodItems) {
this.mlMenuFoodItems = mlMenuFoodItems;
}
public MlMenuFoodItem addMlMenuFoodItem(MlMenuFoodItem mlMenuFoodItem) {
getMlMenuFoodItems().add(mlMenuFoodItem);
mlMenuFoodItem.setMlFoodItem(
this);
return mlMenuFoodItem;
}
public MlMenuFoodItem removeMlMenuFoodItem(MlMenuFoodItem mlMenuFoodItem) {
getMlMenuFoodItems().remove(mlMenuFoodItem);
mlMenuFoodItem.setMlFoodItem(
null);
return mlMenuFoodItem;
}
}

Junction table entity: 连接表实体:

@Entity
@Table
(name="ML_MENU_FOOD_ITEM")
@NamedQuery
(name="MlMenuFoodItem.findAll", query="SELECT m FROM MlMenuFoodItem m")
public class MlMenuFoodItem implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private MlMenuFoodItemPK id;
@Column(name="MENU_QUANTITY_NBR", nullable=false, length=4)
private String menuQuantityNbr;
@ManyToOne
@JoinColumn(name="FOOD_ITEM_NBR", nullable=false, insertable=false, updatable=false)
private MlFoodItem mlFoodItem;
@ManyToOne
@JoinColumn(name="MENU_ITEM_NBR", nullable=false, insertable=false, updatable=false)
private MlMenuItem mlMenuItem;
public MlMenuFoodItem() {
}
public MlMenuFoodItemPK getId() {
return this.id;
}
public void setId(MlMenuFoodItemPK id) {
this.id = id;
}
public String getMenuQuantityNbr() {
return this.menuQuantityNbr;
}
public void setMenuQuantityNbr(String menuQuantityNbr) {
this.menuQuantityNbr = menuQuantityNbr;
}
public MlFoodItem getMlFoodItem() {
return this.mlFoodItem;
}
public void setMlFoodItem(MlFoodItem mlFoodItem) {
this.mlFoodItem = mlFoodItem;
}
public MlMenuItem getMlMenuItem() {
return this.mlMenuItem;
}
public void setMlMenuItem(MlMenuItem mlMenuItem) {
this.mlMenuItem = mlMenuItem;
}
}

Java Config for OpenJPA/Spring Data: 适用于OpenJPA / Spring数据的Java Config:

@Configuration
@EnableJpaRepositories
public
class JpaConfiguration {
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = 
new DriverManagerDataSource();
dataSource.setUrl(
"jdbc:db2://XXXXXXXX:99999/DATABASENAME");
dataSource.setUsername(
"XXXXXXX");
dataSource.setPassword(
"XXXXXXX");
dataSource.setDriverClassName(
"com.ibm.db2.jcc.DB2Driver");
return dataSource;
}
@Bean
public Map<String, Object> jpaProperties() {
Map<String, Object> props = 
new HashMap<String, Object>();
props.put(
"openjpa.RuntimeUnenhancedClasses", "supported");
props.put(
"openjpa.Log", "Runtime=TRACE, SQL=TRACE, MetaData=TRACE, Enhance=TRACE, DefaultLevel=TRACE");
props.put(
"openjpa.ConnectionFactoryProperties", "PrettyPrint=true, PrettyPrintLineLength=72");
props.put(
"openjpa.jdbc.Schema", "XXXXX");
props.put(
"openjpa.DynamicEnhancementAgent", "false");
props.put(
"openjpa.jdbc.DBDictionary", "db2");
return props;
}
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
OpenJpaVendorAdapter openJpaVendorAdapter = 
new OpenJpaVendorAdapter();
openJpaVendorAdapter.setShowSql(
true);
openJpaVendorAdapter.setGenerateDdl(
true);
openJpaVendorAdapter.setDatabase(Database.
DB2);
return openJpaVendorAdapter;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(
entityManagerFactory().getObject());
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef = 
new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(
this.dataSource());
lef.setJpaPropertyMap(
this.jpaProperties());
lef.setJpaVendorAdapter(
this.jpaVendorAdapter());
lef.setPackagesToScan(
this.getClass().getPackage().getName());
return lef;
}

I fixed the issue by dumping openJPA and switching to Hibernate. 我通过转储openJPA并切换到Hibernate解决了该问题。 Not sure if it was an issue with the implementation of OpenJPA, but Hibernate seems to work much better. 不确定OpenJPA的实现是否存在问题,但是Hibernate似乎工作得更好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM