英文:
@Version from org.springframework.data.mybatis.annotations.Version does not get incremented by 1 on update due to condition that break the query
问题
Description
在一个 Spring Boot 1.5.9 应用程序中,
我在 @Entity
上使用了 org.springframework.data.mybatis.annotations.Version
注解,将其放在 version
属性上,以便在每次更新时自动递增版本,但这却导致我的应用程序出现问题。
错误信息为:
update effect 0 row, maybe version control lock occurred.
我可以看到请求以以下方式结束:
"version"="version"+1,
where
"id"=21
and "version"=null
and "version"=null
导致整个请求未编辑任何行。
这是实体的一个示例:
CREATE TABLE "cm_company_postal_address"
(
"id" BIGSERIAL NOT NULL,
"note" VARCHAR(255) DEFAULT NULL,
"city" VARCHAR(255) NOT NULL,
"postal_code" BIGINT DEFAULT NULL,
"c_ref_country_id" BIGINT NOT NULL,
"cm_company_id" BIGINT NOT NULL,
"street_address_line1" VARCHAR NOT NULL,
"street_address_line2" VARCHAR DEFAULT NULL,
"post_box" VARCHAR(20) DEFAULT NULL,
"version" BIGINT DEFAULT NULL,
"created_date_time" TIMESTAMPTZ DEFAULT NULL,
"created_by_id" BIGINT DEFAULT NULL,
"last_modified_date_time" TIMESTAMPTZ DEFAULT NULL,
"last_modified_by_id" BIGINT DEFAULT NULL,
"deleted" BOOLEAN NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id"),
CONSTRAINT company_id_fk FOREIGN KEY ("cm_company_id") REFERENCES "cm_company" ("id")
);
这是 Java 类:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.data.mybatis.annotations.Column;
import org.springframework.data.mybatis.annotations.Condition;
import org.springframework.data.mybatis.annotations.Conditions;
import org.springframework.data.mybatis.annotations.Entity;
import static org.springframework.data.repository.query.parser.Part.Type.CONTAINING;
@Data
@JsonIgnoreProperties("new")
@Entity(table = "cm_company_postal_address")
@EqualsAndHashCode(callSuper = false)
public class PostalAddress {
@Id(strategy = AUTO)
private Long id;
private String description;
@Version
private Integer version;
@CreatedDate
@JsonUnwrapped
@JdbcType(TIMESTAMP)
private Instant createdDateTime;
@LastModifiedDate
@JsonUnwrapped
@JdbcType(TIMESTAMP)
private Instant lastModifiedDateTime;
@CreatedBy
private Long createdById;
@LastModifiedBy
private Long lastModifiedById;
@JsonProperty(value = "deleted")
private Boolean deleted = false;
@Column(name = "cm_company_id")
private Long companyId;
private String city;
private Long postalCode;
private Long countryId;
private String streetAddressLine1;
private String streetAddressLine2;
private String postBox;
}
这是所示实体的 @Repository
:
import com.kopaxgroup.api.companyManagement.domain.postalAddress.geography.PostalAddress;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.data.mybatis.repository.support.MybatisRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
@RepositoryRestResource(exported = false)
public interface PostalAddressRepository extends MybatisRepository<PostalAddress, Long> {
}
这是同一实体的服务接口:
import com.kopaxgroup.api.companyManagement.domain.postalAddress.geography.PostalAddress;
import org.springframework.data.support.CrudService;
public interface PostalAddressService extends CrudService<PostalAddress, Long> {
}
以及它的实现:
import com.kopaxgroup.api.companyManagement.domain.postalAddress.geography.PostalAddress;
import com.kopaxgroup.api.companyManagement.repository.PostalAddressRepository;
import com.kopaxgroup.api.companyManagement.service.PostalAddressService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.support.AbstractCrudService;
import org.springframework.stereotype.Service;
@Service
public class PostalAddressServiceImpl extends AbstractCrudService<PostalAddressRepository, PostalAddress, Long> implements PostalAddressService {
@Autowired
public PostalAddressServiceImpl(PostalAddressRepository repository) {
super(repository);
}
以及这是如何更新实体的方式:
import com.kopaxgroup.api.companyManagement.domain.postalAddress.geography.PostalAddress;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/postal-address")
public class PostalAddressController {
@Autowired
private PostalAddressService postalAddressService;
@PutMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
void modify(@PathVariable("id") Long id, @RequestBody PostalAddress entity) {
entity.setId(id);
postalAddressService.updateIgnore(entity);
}
}
期望
我期望这个实体的 version
列在每次更新时都会递增。
结果
然而,每次更新都会为版本列保留 null
值。
问题
- 如何防止
spring-data-mybatis
在请求末尾添加and "version"=null
?
版本
- spring boot: 1.5.9.RELEASE
- spring-boot-starter-data-mybatis: 1.0.17.RELEASE
英文:
Description
In a Spring Boot 1.5.9 application,
I am using org.springframework.data.mybatis.annotations.Version
annotation within an @Entity
on version
attribute to get a version incremented on each update, but it keep breaking my application.
The error is:
update effect 0 row, maybe version control lock occurred.
I can see that the request end with:
"version"="version"+1,
where
"id"=21
and "version"=null
and "version"=null
cause the whole request to edit 0 row
.
This is an example of entity:
CREATE TABLE "cm_company_postal_address"
(
"id" BIGSERIAL NOT NULL,
"note" VARCHAR(255) DEFAULT NULL,
"city" VARCHAR(255) NOT NULL,
"postal_code" BIGINT DEFAULT NULL,
"c_ref_country_id" BIGINT NOT NULL,
"cm_company_id" BIGINT NOT NULL,
"street_address_line1" VARCHAR NOT NULL,
"street_address_line2" VARCHAR DEFAULT NULL,
"post_box" VARCHAR(20) DEFAULT NULL,
"version" BIGINT DEFAULT NULL,
"created_date_time" TIMESTAMPTZ DEFAULT NULL,
"created_by_id" BIGINT DEFAULT NULL,
"last_modified_date_time" TIMESTAMPTZ DEFAULT NULL,
"last_modified_by_id" BIGINT DEFAULT NULL,
"deleted" BOOLEAN NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id"),
CONSTRAINT company_id_fk FOREIGN KEY ("cm_company_id") REFERENCES "cm_company" ("id")
);
This is the java class:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.data.mybatis.annotations.Column;
import org.springframework.data.mybatis.annotations.Condition;
import org.springframework.data.mybatis.annotations.Conditions;
import org.springframework.data.mybatis.annotations.Entity;
import static org.springframework.data.repository.query.parser.Part.Type.CONTAINING;
@Data
@JsonIgnoreProperties("new")
@Entity(table = "cm_company_postal_address")
@EqualsAndHashCode(callSuper = false)
public class PostalAddress {
@Id(strategy = AUTO)
private Long id;
private String description;
@Version
private Integer version;
@CreatedDate
@JsonUnwrapped
@JdbcType(TIMESTAMP)
private Instant createdDateTime;
@LastModifiedDate
@JsonUnwrapped
@JdbcType(TIMESTAMP)
private Instant lastModifiedDateTime;
@CreatedBy
private Long createdById;
@LastModifiedBy
private Long lastModifiedById;
@JsonProperty(value = "deleted")
private Boolean deleted = false;
@Column(name = "cm_company_id")
private Long companyId;
private String city;
private Long postalCode;
private Long countryId;
private String streetAddressLine1;
private String streetAddressLine2;
private String postBox;
}
This is my @Repository
for the presented entity:
import com.kopaxgroup.api.companyManagement.domain.postalAddress.geography.PostalAddress;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.data.mybatis.repository.support.MybatisRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
@RepositoryRestResource(exported = false)
public interface PostalAddressRepository extends MybatisRepository<PostalAddress, Long> {
}
This is the service interface for the same entity:
import com.kopaxgroup.api.companyManagement.domain.postalAddress.geography.PostalAddress;
import org.springframework.data.support.CrudService;
public interface PostalAddressService extends CrudService<PostalAddress, Long> {
}
And it's implementation:
import com.kopaxgroup.api.companyManagement.domain.postalAddress.geography.PostalAddress;
import com.kopaxgroup.api.companyManagement.repository.PostalAddressRepository;
import com.kopaxgroup.api.companyManagement.service.PostalAddressService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.support.AbstractCrudService;
import org.springframework.stereotype.Service;
@Service
public class PostalAddressServiceImpl extends AbstractCrudService<PostalAddressRepository, PostalAddress, Long> implements PostalAddressService {
@Autowired
public PostalAddressServiceImpl(PostalAddressRepository repository) {
super(repository);
}
And this is how I update the entity:
import com.kopaxgroup.api.companyManagement.domain.postalAddress.geography.PostalAddress;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/postal-address")
public class PostalAddressController {
@Autowired
private PostalAddressService postalAddressService;
@PutMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
void modify(@PathVariable("id") Long id, @RequestBody PostalAddress entity) {
entity.setId(id);
postalAddressService.updateIgnore(entity);
}
}
Expected
I expect to have the version
column of this entity to be incremented on each update.
Result
Instead, each update keep a null
value for version column.
Question
- How can I prevent
spring-data-mybatis
from appendingand "version"=null
at the end of the request?
Version
- spring boot: 1.5.9.RELEASE
- spring-boot-starter-data-mybatis: 1.0.17.RELEASE
答案1
得分: 0
Spring-data还有它自己的版本注解:org.springframework.data.annotation.Version
。这个注解在spring-data-mybatis库中使用。
英文:
Spring-data has also its own version annotation: org.springframework.data.annotation.Version
. This annotation is used in spring-data-mybatis lib.
专注分享java语言的经验与见解,让所有开发者获益!
评论