2016-10-03 56 views
0

请帮我这样的问题 - 我有抽象类 和两个孩子:麻烦与Hibernate继承

@Table(name = "abstract_partner") 
@Inheritance(strategy= InheritanceType.JOINED) 
public abstract class AbstractPartner { 

@Id 
protected Long id; 
protected String name; 
protected String endpoint; 
protected String code; 
@Column(name = "api_key") 
protected String apiKey; 

public Long getId() { 
    return id; 
} 

public void setId(Long id) { 
    this.id = id; 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 

public String getEndpoint() { 
    return endpoint; 
} 

public void setEndpoint(String endpoint) { 
    this.endpoint = endpoint; 
} 

public String getCode() { 
    return code; 
} 

public void setCode(String code) { 
    this.code = code; 
} 

@Override 
public abstract boolean equals(Object o); 

@Override 
public int hashCode() { 
    return Objects.hash(id); 
} 

public String getApiKey() { 
    return apiKey; 
} 

public void setApiKey(String apiKey) { 
    this.apiKey = apiKey; 
} 

}

CustomerPartnerGroupEntity

@Entity 
@Table(name = "customer_partner_group") 

public class CustomerPartnerGroupEntity extends AbstractPartner{ 

@Override 
public boolean equals(Object o) { 
    if (this == o) return true; 
    if (!(o instanceof CustomerPartnerGroupEntity)) return false; 
    CustomerPartnerGroupEntity that = (CustomerPartnerGroupEntity) o; 
    return Objects.equals(id, that.id); 
} 
} 

NetworkPartner

@Entity 
@Table(name = "network_partners") 

public class NetworkPartner extends AbstractPartner{ 

@OneToOne(mappedBy = "partner", fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
@JsonIgnore 
private NetworkPartnerConfiguration configuration; 

@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "payment_provider_id") 
@JsonIgnore 
private PaymentProviderEntity paymentProvider; 


@Override 
public boolean equals(Object o) { 
    if (this == o) return true; 
    if (!(o instanceof NetworkPartner)) return false; 
    NetworkPartner that = (NetworkPartner) o; 
    return Objects.equals(id, that.id); 
} 

public NetworkPartnerConfiguration getConfiguration() { 
    return configuration; 
} 

public void setConfiguration(NetworkPartnerConfiguration configuration) { 
    this.configuration = configuration; 
} 

public PaymentProviderEntity getPaymentProvider() { 
    return paymentProvider; 
} 

public void setPaymentProvider(PaymentProviderEntity paymentProvider) { 
    this.paymentProvider = paymentProvider; 
} 
} 

,并尝试通过Hibernate来实现继承与战略 - JOINED 但是当我使用这个策略,我得到异常:

Caused by: org.springframework.beans.factory.BeanCreationException: Error  creating bean with name 'entityManagerFactory' defined in class path resource [common-beans.xml]: Invocation of init method failed; nested exception is java.util.NoSuchElementException 
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1572) 
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539) 
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) 
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) 
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) 
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) 
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:960) 
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:749) 
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480) 
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:125) 
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60) 
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:109) 
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:261) 
at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:68) 
at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86) 
... 24 more 
Caused by: java.util.NoSuchElementException 
at java.util.ArrayList$Itr.next(ArrayList.java:854) 
at org.hibernate.cfg.annotations.TableBinder.linkJoinColumnWithValueOverridingNameIfImplicit(TableBinder.java:487) 
at org.hibernate.cfg.PkDrivenByDefaultMapsIdSecondPass.doSecondPass(PkDrivenByDefaultMapsIdSecondPass.java:54) 
at org.hibernate.cfg.Configuration.processSecondPassesOfType(Configuration.java:1386) 
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1337) 
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1730) 
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:94) 
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:905) 
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:890) 
at org.springframework.orm.jpa.vendor.SpringHibernateEjbPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateEjbPersistenceProvider.java:51) 
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:343) 
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318) 
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1631) 
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1568) 
... 39 more 

奇怪的事情 - 如果我选择另一个策略(单个表或TABLE_PER_CLASS)错误不会出现

回答

0

仅通过将策略从JOINED更改为SINGLE_TABLE将无法解决此问题。您需要在父类中添加@DiscriminatorColumn,并且每个父类/子类都应该有@DiscriminatorValue来区分单个表中的记录。

下面是一个例子代码:
Employee.java

import javax.persistence.Column; 
import javax.persistence.DiscriminatorColumn; 
import javax.persistence.DiscriminatorType; 
import javax.persistence.DiscriminatorValue; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.Inheritance; 
import javax.persistence.InheritanceType; 
import javax.persistence.Table; 

@Entity 
@Table(name = "employee_tph") 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name = "object_type", discriminatorType = DiscriminatorType.STRING) 
@DiscriminatorValue(value = "Employee") 
public class Employee { 
@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
@Column(name = "Employee_Id") 
private long empId; 

@Column(name = "Employee_Name") 
private String name; 

public long getEmpId() { 
    return empId; 
} 

public void setEmpId(long empId) { 
    this.empId = empId; 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 

} 

Contract_Employee类

import javax.persistence.Column; 
import javax.persistence.DiscriminatorValue; 
import javax.persistence.Entity; 

@Entity 
@DiscriminatorValue(value = "Contract_Employee") 
public class Contract_Employee extends Employee { 
@Column(name = "pay_per_hour") 
private float pay_per_hour; 

@Column(name = "contract_period") 
private String contract_period; 

public float getPay_per_hour() { 
    return pay_per_hour; 
} 

public void setPay_per_hour(float pay_per_hour) { 
    this.pay_per_hour = pay_per_hour; 
} 

public String getContract_period() { 
    return contract_period; 
} 

public void setContract_period(String contract_period) { 
    this.contract_period = contract_period; 
} 

} 

Regular_Employee类

import javax.persistence.Column; 
import javax.persistence.DiscriminatorValue; 
import javax.persistence.Entity; 

@Entity 
@DiscriminatorValue(value = "Regular_Employee") 
public class Regular_Employee extends Employee { 
@Column(name = "salary") 
private float salary; 

@Column(name = "bonus") 
private float bonus; 

public float getSalary() { 
    return salary; 
} 

public void setSalary(float salary) { 
    this.salary = salary; 
} 

public float getBonus() { 
    return bonus; 
} 

public void setBonus(float bonus) { 
    this.bonus = bonus; 
} 

} 

主要类功能

public static void main(String[] args) { 
    SessionFactory sessionFactory=HibernateUtil.getSessionAnnotationFactory(); 
    Session session=sessionFactory.openSession(); 

    Transaction tx=session.beginTransaction(); 

    Employee e1=new Employee(); 
    e1.setName("Rohit"); 

    Regular_Employee r1=new Regular_Employee(); 
    r1.setBonus(1000.50f); 
    r1.setName("Peter"); 
    r1.setSalary(45000.56f); 

    Contract_Employee c1=new Contract_Employee(); 
    c1.setName("Harry"); 
    c1.setContract_period("4 yrs 5 months"); 
    c1.setPay_per_hour(45.5f); 

    session.persist(e1); 
    session.persist(c1); 
    session.persist(r1); 

    tx.commit(); 
    session.close(); 
    System.out.println("success.."); 
} 
+0

作为,如果我改变策略@Inheritance(我理解数据库结构问题strategy = InheritanceType.JOINED)转换为TABLE_PER_CLASS的SINGLE_TABLE,则不会出现错误 – OlegD

+0

当我尝试执行时出现错误 – OlegD

+0

是否意味着当您将策略从JOINED更改为SINGLE_TABLE时发生错误? –

0

错误出现,当我尝试运行

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:common-beans.xml" }) 
@TransactionConfiguration(defaultRollback = true) 
@Transactional 
public class PartnerDAOTest { 

private Partner partner; 
private SystemUser user; 

@Autowired 
private PartnerDAO partnerDAO; 
@Autowired 
private SystemUserService systemUserService; 
// 
@Autowired 
private SystemUserRoleService systemUserRoleService; 

static { 
    System.setProperty("envTarget", "local"); 
} 


public PartnerDAOTest() { 
} 

@Before 
public void testSave() { 
    user = new SystemUser(); 
    user.setEmail("[email protected]"); 
    user.setPassword("11"); 
    // 
    user.setRole(systemUserRoleService.findByName(SystemUserRole.Name.ROLE_ADMIN)); 

    this.systemUserService.persist(user); 

    Assert.assertTrue(user.getId() > 0); 

    partner = new Partner(); 
    partner.setEnabled(0); 
    partner.setPkey(UUID.randomUUID().toString()); 
    partner.setApiKey(UUID.randomUUID().toString().substring(0, 32)); 

    Set<SystemUser> users = new HashSet<>(); 
    users.add(user); 
    //partner.setSystemUsers(users); 
    Set<Partner> partners = new HashSet<>(); 
    partners.add(partner); 
    //user.setPartners(partners); 

    this.partnerDAO.persist(partner); 

    Assert.assertNotNull(partner); 
    Assert.assertTrue(partner.getId() > 0); 
} 

@Test 
public void testGetById() { 
    Partner found = this.partnerDAO.get(partner.getId()); 

    Assert.assertNotNull(found); 
    Assert.assertTrue(partner.getId() == found.getId()); 
} 

@Test 
public void testUpdate() { 
    partner.setEnabled(1); 
    this.partnerDAO.update(partner); 

    Assert.assertEquals(partner.getEnabled(), 1); 
} 

@Test 
public void testFindByIds() { 
    List<Long> ids = new ArrayList<>(); 
    ids.add(partner.getId()); 

    Set<Partner> partners = this.partnerDAO.findByIds(ids); 
    Assert.assertTrue(CollectionUtils.isNotEmpty(partners)); 
} 

}