Spring Java、Hibernate——Can';t在使用单独的嵌入密钥类持久化实体后检索id

Spring Java、Hibernate——Can';t在使用单独的嵌入密钥类持久化实体后检索id,spring,hibernate,jpa,spring-boot,Spring,Hibernate,Jpa,Spring Boot,我正在开发一个示例Springboot服务器应用程序,并使用hibernate for JPA。我使用的是一个通用存储库模式,它对我的实体执行所有CRUD操作。我举这个例子: 我遇到的。(我的想法是为所有CRUD操作提供一个类似的实现,而不是在每个服务/DAO或每个实体的存储库实现中明确说明一个实现)在上面的示例中,@ID属性与实体在同一个类中。因此,我能够持久化一个实体,并且id将反映在entityManager.persist(object)之后的对象中 在我的代码中,键类是分开的,它在实体

我正在开发一个示例Springboot服务器应用程序,并使用hibernate for JPA。我使用的是一个通用存储库模式,它对我的实体执行所有CRUD操作。我举这个例子: 我遇到的。(我的想法是为所有CRUD操作提供一个类似的实现,而不是在每个服务/DAO或每个实体的存储库实现中明确说明一个实现)在上面的示例中,@ID属性与实体在同一个类中。因此,我能够持久化一个实体,并且id将反映在entityManager.persist(object)之后的对象中

在我的代码中,键类是分开的,它在实体类中被引用。在EntityManager上调用persist时,会在数据库中创建一行(因为主键的列在数据库中设置为自动递增),但在调用persist()后,相同的ID不会反映在对象中。key类中的my ID属性始终设置为0,这是默认的int值。我想知道是否有一种方法可以通过会话或EntityManager获取插入对象的ID。另外,在实体类本身中不包含主键的情况下,是否有其他解决此问题的策略。(到目前为止,我已经查看了SO上的多篇帖子,但还没有找到解决问题的方法。)

实体类

@Entity
@Table(name = "articles")
public class SampleArticle extends AbstractDomainObject {
/** The serialVersionUID. */
private static final long serialVersionUID = 7072648542528280535L;
/** Uniquely identifies the article. */
@EmbeddedId
@AttributeOverride(name = "articleId", column = @Column(name = "article_id"))
@GeneratedValue(strategy = GenerationType.IDENTITY)
//@GeneratedValue(strategy = GenerationType.AUTO)
private SampleArticleKey key;
/** Indicates the title. */
@Column(name = "title")
private String title;
关键类

@Embeddable
public class SampleArticleKey extends AbstractDomainKey {
/**
 * Serial version id.
 */
private static final long serialVersionUID = 1325990987094850016L;
/** The article id. */
private int articleId;
存储库类

@Repository
@Transactional
public class SampleArticleRepository extends 
AbstractRepository<SampleArticle, SampleArticleKey> implements 
ISampleArticleRepository<SampleArticle, SampleArticleKey> {
/*
 * (non-Javadoc)
 * @see
 * com.wpi.server.entity.repository.ISampleArticleRepository#addArticle
 * (java.lang.Object)
 */
@Override
public SampleArticle create(SampleArticle article) throws Exception {
    return super.create(article);
}
@存储库
@交易的
公共类SampleArticleRepository扩展
抽象存储库实现
ISampleActureRepository{
/*
*(非Javadoc)
*@见
*com.wpi.server.entity.repository.ISampleArticleRepository#addArticle
*(java.lang.Object)
*/
@凌驾
公共SampleArticle创建(SampleArticle文章)引发异常{
返回super.create(文章);
}
抽象存储库

@Transactional
public abstract class AbstractRepository<T extends AbstractDomainObject, K 
extends AbstractDomainKey> {
/** The entity manager. */
@PersistenceContext
private EntityManager entityManager;
/** The Constant LOGGER. */
private static final Logger LOGGER = Logger.getLogger(AbstractRepository.class.getName());

/**
 * Persist the given object at persistence storage.
 *
 * @param object
 *            The object extending {@link AbstractDomainObject} which needs
 *            to be inserted.
 * @return object of type {@link AbstractDomainObject} with the newly
 *         generated id.
 * @throws Exception
 *             If unable to insert data.
 */
public T create(T object) throws Exception {
    final Session session = entityManager.unwrap(Session.class);
    session.getTransaction().begin();
    session.save(object);
    session.flush();
    session.getTransaction().commit();
    session.close();
    LOGGER.fine("Entity CREATED successfully.");
    return object;
};
@Transactional
公共抽象类抽象存储库{
/**实体管理器*/
@持久上下文
私人实体管理者实体管理者;
/**常数记录器*/
私有静态最终记录器Logger=Logger.getLogger(AbstractRepository.class.getName());
/**
*在持久性存储中持久化给定对象。
*
*@param对象
*扩展{@link AbstractDomainObject}的对象需要
*待插入。
*类型为{@link AbstractDomainObject}的@return对象
*生成的id。
*@抛出异常
*如果无法插入数据。
*/
公共T创建(T对象)引发异常{
最终会话Session=entityManager.unwrap(Session.class);
session.getTransaction().begin();
session.save(对象);
session.flush();
session.getTransaction().commit();
session.close();
LOGGER.fine(“实体创建成功”);
返回对象;
};

让我给你一个工作的可嵌入密钥示例。它可能会有所帮助。 首先覆盖equals()和hashCode()方法,以便Hibernate正确识别现金中的对象

现在可以持久化对象了


让我知道这是否有帮助,或者您在这方面有其他问题。

在可嵌入的复合键中应该覆盖2个方法:hashCode(),equals()对于正确的工作,请给出一部分代码,在其中设置复合键并持久化对象。我已在我的键类和实体类中重写了这两个方法。此外,调用persist是从我的服务类调用的,这反过来又会调用存储库。
try{final SampleArticle domainObj=new SampleArticle();domainObj.setTitle(dto.getTitle());domainObj.setCategory(dto.getCategory());domainObj.setKey(todominkey(dto));article=sampleArticleRepo.create(article);
这里的最后一行调用上面发布的samplearticlererepository类中的create方法。