我在我的应用程序中使用Maven,Hibernate和Spring。我已经在自己的包中实现了实体类,DAO类和服务类。测试服务时遇到问题。当单元测试此特定服务正在调用的DAO方法时,预期结果。但是在测试使用此DAO方法的服务方法时,我得不到相同的结果。我认为这个问题与整合有关。服务使用@Transactional进行注释。数据源和服务在测试服务类中使用@Autowired进行注释。我附上了服务测试类的上下文配置。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="class1Dao"
class="org.project.datalayer.implementation.Class1DaoImplementation">
</bean>
<bean id="service"
class="org.project.services.implementation.Service1Implementation">
<property name="class1Dao">
<ref bean="class1Dao" />
</property>
</bean>
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"
value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem:project" />
<property name="username" value="username" />
<property name="password" value="password" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
<context:annotation-config />
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory"
ref="entityManagerFactory" />
</bean>
<tx:annotation-driven />
</beans>
请求的示例代码:
实体
@MappedSuperclass
public abstract class ClassBase implements Serializable {
@Id()
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Integer id;
@Version
private int version = 0;
private Date created;
private Date updated;
/**
* @return the id
*/
public Integer getId() {
return id;
}
@PrePersist
@Column(name = "created", nullable = false)
protected void onCreate() {
this.created = new Date();
}
@PreUpdate
@Column(name = "updated", nullable = false)
protected void onUpdate() {
this.updated = new Date();
}
/**
* @return the version
*/
public int getVersion() {
return this.version;
}
/**
* @param version the version to set
*/
public void setVersion(int version) {
this.version = version;
}
/**
* @return the created
*/
public Date getCreated() {
return this.created;
}
/**
* @return the updated
*/
public Date getUpdated() {
return this.updated;
}
}
@Entity
@Table(name = "class1")
class Class1 extends ClassBase {
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "class1_id")
private List<Class2> class2List = new ArrayList<Class2>();
@OneToMany(mappedBy = "class1", cascade = CascadeType.ALL)
private List<Class1Class4> class1Class4List = new ArrayList<Class1Class4>();
}
@Entity
@Table(name = "class1_class4")
class Class1Class4 extends ClassBase {
@ManyToOne(optional = false, cascade = CascadeType.ALL)
@JoinColumn(name="class4_id")
private Class4 class4;
@ManyToOne(optional = false, cascade = CascadeType.ALL)
@JoinColumn(name="class1_id")
private Class1 class1;
}
@Entity
@Table(name = "class2")
class Class2 extends ClassBase {
@OneToMany(mappedBy = "class1", cascade = CascadeType.ALL)
private Class1 class1;
@OneToMany(mappedBy = "class2", cascade = CascadeType.ALL)
private List<Class2Class3> class2Class3List = new ArrayList<Class2Class3>();
}
@Entity
@Table(name = "class2_class3")
class Class2Class3 extends ClassBase {
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "class2_id")
private Class2 class2;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "class3_id")
private Class3 class3;
}
@Entity
@Table(name = "class3")
class Class3 extends ClassBase {
@OneToMany(mappedBy = "class3", cascade = CascadeType.ALL)
private List<Class2Class3> class2Class3List = new ArrayList<Class2Class3>();
@OneToOne(cascade = CascadeType.ALL)
@JoinColumns({
@JoinColumn(name = "class4_id",
referencedColumnName = "id")
})
private Class4 class4;
@ManyToOne(cascade = CascadeType.ALL)
@ForeignKey(name = "fk_class3_to_parent", inverseName = "fk_parent_to_class3")
private Class3 parent;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
private Set<Class3> descendantList = new HashSet<Class3>();
...
}
@Entity
@Table(name = "class4")
class Class4 extends ClassBase {
@OneToOne(mappedBy="class4")
private Class3 class3;
@OneToMany(mappedBy = "class4", cascade = CascadeType.ALL)
private List<Class1Class4> class1Class4List = new ArrayList<Class1Class4>();
}
DAO
public class Class1DaoImplementation extends BaseDaoTemplate<Class1> implements Class1Dao {
public Class1DaoImplementation() {
super(Class1.class);
}
public Class getPublicByPrimaryKey(Integer id) {
EntityManager em = getEntityManager();
Query q =
em.createQuery("SELECT distinct(p) FROM Class1 p"
+ " INNER JOIN p.class5 ps"
+ " INNER JOIN FETCH p.class2 it"
+ " INNER JOIN FETCH it.class2Class3List itfs"
+ " INNER JOIN FETCH itfs.class3 f"
+ " LEFT JOIN FETCH f.parent fp" // PROBLEM: null when running integration test
+ " LEFT JOIN FETCH f.descendants fd"
+ " WHERE p.id = :class1Id"
+ " AND ps.id = 5"
+ " ORDER BY p.id"
);
q.setParameter("class1Id", id);
return (Class1) q.getSingleResult();
}
}
问题可能与方法getPublicByPrimaryKey的查询的复杂性有关吗?但是,如果方法在单元测试期间工作正常,为什么在运行集成测试时它的工作方式不同?
测试数据:
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<!--ELEMENT CLASS3 EMPTY-->
<!--ATTLIST CLASS3
PARAM1 CDATA #REQUIRED
ID CDATA #REQUIRED
PARAM2 CDATA #REQUIRED
PARENT_ID CDATA #IMPLIED
-->
]>
<class3 param1="0" id="1" param2="5" />
<class3 param1="0" id="2" param2="5" />
<class3 param1="0" id="3" param2="5" parent_id="1" />
<class3 param1="0" id="4" param2="5" parent_id="1" />
<class3 param1="0" id="5" param2="5" parent_id="2" />
加载测试数据: 连接连接= DataSourceUtils.getConnection(数据源);
ArrayList<String> dbunitFilePaths = new ArrayList<String>();
dbunitFilePaths.add("/class3.xml");
ListIterator<String> dbunitFilePathsIterator = dbunitFilePaths.listIterator();
try {
IDatabaseConnection dbUnitConnection =
new DatabaseConnection(connection);
String dbunitFilePath;
ClassPathResource xml;
IDataSet[] dataSets = new IDataSet[dbunitFilePaths.size()];
for(int i = 0; i < dbunitFilePaths.size(); i++) {
dbunitFilePath = dbunitFilePathsIterator.next();
xml = new ClassPathResource(dbunitFilePath);
dataSets[i] = new FlatXmlDataSetBuilder().build(xml.getInputStream());
}
CompositeDataSet compositeDataSet = new CompositeDataSet(dataSets);
DatabaseOperation.CLEAN_INSERT.execute(dbUnitConnection,
compositeDataSet);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
如果我像这样编辑文件加载方法......
...
ListIterator<String> dbunitFilePathsIterator = dbunitFilePaths.listIterator();
FlatXmlDataSetBuilder flatXmlDataSetBuilder;
try {
...
xml = new ClassPathResource(dbunitFilePath);
flatXmlDataSetBuilder = new FlatXmlDataSetBuilder().setColumnSensing(true);
dataSets[i] = flatXmlDataSetBuilder.build(xml.getInputStream());
}
...
...然后我得到以下消息,为所有BUT第一个测试方法:
java.sql.SQLException: Integrity constraint violation FK_CLASS3_TO_PARENT table: CLASS3
答案 0 :(得分:0)
您是如何设置数据的?通过直接SQL插入?从文件加载?或者,使用Hibernate(在setup()等中)?
如果你是通过Hibernate设置数据,你在安装后是否刷新了?或者,您是否在设置过程中设置了f.parent的引用,即使您已在父obj中设置了descendantList? Hibernate的第一级缓存可能会保留您通过Hibernate创建的空父Class3实例并返回给您。