java – 解释使用Hibernate映射自动递增复合id序列的行为
|
我有一张桌子 CREATE TABLE `SomeEntity` (
`id` int(11) NOT NULL AUTO_INCREMENT,`subid` int(11) NOT NULL DEFAULT '0',PRIMARY KEY (`id`,`subid`),
我有一个实体类,其中有一个自动增量字段.我想要读取自动递增id,当它被持久化分配给它 吸气剂的注释如下 private long id;
private int subid;
@Id
@GeneratedValue **//How do i correct this to have multiple rows with same id and different subid**
@Column(name = "id")
public long getId() {
return id;
}
@Id
@Column(name = "subid")
public int getSubid() {
return subid;
}
我想要有实体 id 1 subid 0 id 1 subid 1 id 1 subid 2 id 2 subid 0 subid在数据库中是默认值0,我以编程方式增加对该行的更新. @Transactional
@Override
public void daoSaveEntity(SomeEntity entity) {
entityManager.persist(entity);
}
现在在这个事务之外,我试图获得分配的自动递增ID @Override
public long serviceSaveEntity(SomeEntity entity) {
dao.daoSaveEntity(entity);
return entity.getId();
}
我从网络服务中呼叫这个 @POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response createEntity(SomeEntity entity) {
更新方法如下 @Transactional
public void updateReportJob(SomeEntity someEntity) {
Query query =
entityManager
.createQuery("UPDATE SomeEntity SET state=:newState WHERE id = :id");
query.setParameter("newState","PASSIVE");
query.setParameter("id",id);
query.executeUpdate();
double rand = Math.random();
int i = (int) (rand * 300);
try {
Thread.sleep(i); //only to simulate concurrency issues
} catch (InterruptedException e) {
e.printStackTrace();
}
List<Integer> resList =
entityManager.createQuery("select max(subid) from SomeEntity WHERE id = :id")
.setParameter("id",jobId).getResultList();
// Increment old subid by 1
int subid = resList.get(0);
SomeEntity.setsubid(subid + 1);
SomeEntity.setState("ACTIVE");
// entityManager.merge(SomeEntity);
entityManager.persist(SomeEntity);
}
我从N线程发送N个并发更新,实体为Id 1,其他几个属性如下 SomeEnity entity = new SomeEntity(); entity.setId(1);
long num = Thread.currentThread().getId();
entity.setFieldOne("FieldOne" + num);
entity.setFieldTwo("" + i);
entity.setFieldThree("" + j);
i++;
j++;
案例1具有@Id和idid上的@Id注释和更新中的“entityManager.persist” id 1 subid 0 id 1 subid 1 id 1 subid 2 .. .... id 1 subid 150 子系统总是增量,竞争条件只是因为竞争条件而被定义为ACTIVE 案例2带有@Id和idid上的@Id注释和更新中的“entityManager.merge” id 1 subid 0 案例3使用@GeneratedValue和@Id在id和** NO @Id注释在subid和entityManager.persist在更新** 情况3使用@GeneratedValue和@Id对id和** NO @Id注释在subid和entityManager.merge在更新** id 1 subid 0 下次更新后 id 1 subid 1 在每次更新之后,相同的行被更新(一次只导致一行) id 1 subid 2 案例4与案例3相同,并发更新 org.hibernate.HibernateException: More than one row with the given identifier was found: 1 数据库状态是 案例5使用@GeneratedValue和@Id对idid和@Id注释在subid上 请解释原因.从我知道的方法的javadoc 持久化 – 使一个实例被管理和持久化. merge – 将给定实体的状态合并到当前持久性上下文中. 我的问题更多的是Hibernate如何管理注释. 我正在使用hibernate 3.6 mysql 5和spring 4 解决方法因为id字段已经是唯一的并且自动递增,所以在这种情况下你不需要一个复合的id,所以你的实体看起来像这样:@Id
@Column(name = "id")
public long getId() {
return id;
}
@Column(name = "subid")
public int getSubid() {
return subid;
}
实体可以通过id使用实体管理器: entityManager.find(MyEntity.class,entityId); 或者您可以使用同时具有id和subid的查询来获取实体: MyEntity myEntity = entityManager.createTypeQuery("select me from MyEntity where id = :id and subid = :subid",MyEntity.class)
.setParameter("id",entityId)
.setParameter("subid",entitySubId)
.getSingleResult();
Hibernate还有一个可以从数据库列获取id的SelectGenerator,当数据库使用触发器生成ID时,这是非常有用的. 不幸的是,它不适用于组合ids,所以你会写下你自己的扩展的SelectGenerator或使用单个字符串id_sub_id列,将id和sub-id组合成一个VARCHAR列: '1-0' '1-1' '2-0' '2-1' 您必须使用数据库特定的存储过程编写数据库触发器来更新两列,并将两列集合到VARCHAR存储过程中.然后,使用标准SelectGenerator将聚合列映射到字符串字段: @Id
@Column(name = "id_sub_id")
@GeneratedValue( strategy = "trigger" )
@GenericGenerator(
name="trigger",strategy="org.hibernate.id.SelectGenerator",parameters = {
@Parameter( name="keys",value="id_sub_id" )
}
)
public String getId() {
return id;
} (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
