EntityManager.merge() 可以插入新对象并更新现有对象.
为什么要使用persist()(只能创建新对象)?
我正在使用JPA(EclipseLink)和Spring.假设我有一个带有自动生成ID的简单实体:
@Entity
public class ABC implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
// ...
}
Run Code Online (Sandbox Code Playgroud)
在我的DAO类中,我有一个调用persist()此实体的insert方法.我希望该方法返回新实体的生成ID,但是当我测试它时,它返回0.
public class ABCDao {
@PersistenceContext
EntityManager em;
@Transactional(readOnly=false)
public int insertABC(ABC abc) {
em.persist(abc);
// I WANT TO RETURN THE AUTO-GENERATED ID OF abc
// HOW CAN I DO IT?
return abc.id; // ???
}
}
Run Code Online (Sandbox Code Playgroud)
我还有一个包装DAO的服务类,如果这有所不同:
public class ABCService {
@Resource(name="ABCDao")
ABCDao abcDao;
public int addNewABC(ABC abc) {
return abcDao.insertABC(abc);
}
}
Run Code Online (Sandbox Code Playgroud) 我的entityManager persist()从序列获取id并将其放到我的Image对象中,但Image对象本身没有显示在数据库中.EntityManager.flush()给出了一个错误,所以我不能这样提交.这是我的代码.
@Repository
public class ImageDaoImpl extends BaseDao implements ImageDao {
@PersistenceContext
protected EntityManager entityManager;
@Override
@Transactional
public void create(Image image) {
JpaTemplate jpaTemplate = getJpaTemplate(entityManager);
jpaTemplate.persist(image);
}
Run Code Online (Sandbox Code Playgroud)
@Repository
public class BaseDao {
private JpaTemplate jpaTemplate;
public JpaTemplate getJpaTemplate(EntityManager entityManager){
if(jpaTemplate == null)
jpaTemplate = new JpaTemplate(entityManager);
return jpaTemplate;
}
Run Code Online (Sandbox Code Playgroud)
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
</bean>
</property>
<property name="persistenceUnitName" value="sample"></property>
</bean>
<!-- DataSource …Run Code Online (Sandbox Code Playgroud) 我有以下问题.我有3个实体,我正在使用OneToOne单向:
ENTITY1
@Entity
public class Entity1 implements Serializable{
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
Long id;
String name;
String value;
}
Run Code Online (Sandbox Code Playgroud)
ENTITY2
@Entity
public class Entity2 implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@OneToOne(cascade={CascadeType.MERGE, CascadeType.PERSIST})
Entity1 entity1;
public Entity1 getEntity1() {
return entity1;
}
String name;
String value;
}
Run Code Online (Sandbox Code Playgroud)
ENTITY3
@Entity
public class Entity3 implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
Long id;
@OneToOne(cascade={CascadeType.MERGE, CascadeType.PERSIST})
private Entity1 entity1;
public Entity1 getEntity1() {
return entity1;
}
public void setEntity1(Entity1 entity1) {
this.entity1 = entity1;
} …Run Code Online (Sandbox Code Playgroud) 我正在使用带有JavaDB的EclipseLink,每当我尝试持久保存新用户实体时,我都会收到与新用户实体的ID字段为空的事实相关的错误.我知道它是空的 - 它应该是因为ID字段是作为数据库中的标识生成的.还是我错了?我尝试将@GeneratedValue添加到实体,但无论使用何种生成策略,都会导致错误.我也看过这里,这里和这里,但这些问题似乎与我的问题没有完全相关.下面的例外总是在调用EntityManager.persist(用户)时发生.
我也尝试删除@NotNull和@GeneratedValue,奇怪的是,它已经超过了持久调用 - 但只是在提交时失败.据我所知,我已经把一切都搞定了.所以问题是:为什么这个应用程序无法添加新用户,我需要做些什么来修复它?
用户实体:
@Entity(name = "User")
@Table(name = "USERS")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Column(name = "IDENTIFIER", nullable = false,unique = true)
private Long identifier;
// class shortened for brevity
}
Run Code Online (Sandbox Code Playgroud)
对应这个SQL脚本:
create table "USERSDBADMIN".USERS
(
IDENTIFIER BIGINT not null primary key GENERATED ALWAYS AS IDENTITY
(START WITH 0, INCREMENT BY 1),
USERNAME VARCHAR(50) not null,
EMAIL …Run Code Online (Sandbox Code Playgroud) 我正在使用JPA toplink-essential和SQL Server 2008
我的目标是获取将要插入表中的数据的自动增量主键值.我知道在JDBC中,有getInsertedId()方法,它给你自动增加主id的id(但是在执行insert语句之后)
在JPA中,我发现@GenratedValue annotation可以做到这一点.
@Entity
@Table(name = "tableOne")
public class TableOne implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "tableId")
private Integer tableId;
Run Code Online (Sandbox Code Playgroud)
现在,如果我运行下面的代码,它应该给我自动增加的id 但它返回NULL ...
EntityManager em = EmProvider.getInstance().getEntityManagerFactory().createEntityManager();
EntityTransaction txn = em.getTransaction();
txn.begin();
TableOne parent = new TableOne();
em.persist(parent); //here I assume that id is pre-generated for me.
System.out.println(parent.getTableId()); //this returns NULL :(
Run Code Online (Sandbox Code Playgroud) 事实证明,即使没有手动提交事务,在提交TX之前,该人在调用save()方法之后也有一个ID.
数据库不负责协助ID字段吗?如果是这样,在提交之前如何填写ID字段?在提交TX之前是否与DB进行任何通信?
基于各种糟糕的经历,我作为Java程序员的经验法则只是实现equals()和hashCode()不可变对象,其中对象的两个实例确实是可以互换的.
基本上我想避免像HashMap链接中的关键问题那样的情况,或者如下所示:
在我的Java职业生涯中,除了(1)值对象和(2)将东西放入集合之外,我还没有找到很多用处.我还发现,不变性+复制和修改构造函数/构建器通常比定位器更快乐.两个对象可能具有相同的ID,并且可能表示相同的逻辑实体,但如果它们具有不同的数据 - 如果它们在不同时间表示概念实体的快照 - 则它们不是.equals() equal()
无论如何,我现在在Hibernate商店,我更熟悉Hibernate的同事告诉我这种方法不会起作用.具体而言,声称似乎是在以下情况中 -
h1.h4.-除非h1.equals(h4)(或许h4.equals(h1),我不太清楚,但我希望它是传递反正所以不管),Hibernate将不能够告诉这些都是一样的东西,坏的事情会发生.
那么,我想知道的是:
equals()用于什么?h1并且h4相同,它是如何(以及我们如何)跟踪哪一个是修改版本?注:我读过实现equals()和hashCode()在Hibernate文档,它不处理,我担心的情况来看,至少直接,也没有任何细节什么的Hibernate真正需要出来解释equals()和hashCode().Hibernate中的equals和hashcode的答案也没有,或者我不打算发布这个.