gpt4 book ai didi

java - 将一对 @ManyToOne 相关属性标记为唯一。可能的?

转载 作者:行者123 更新时间:2023-12-01 04:47:40 25 4
gpt4 key购买 nike

我有一个典型的例子,一个POST有很多TAGS,一个TAG有很多POST。我没有使用典型的 @ManyToMany,而是在中间使用了一个名为 TAGPOST 的域对象,它还允许我在其中包含有用的数据,例如当帖子被标记为给定标签时,每个 POST 和 TAG 都与 TAGPOST 处于 @OneToMany 关系。

具体要求是一个帖子不能包含两次相同的标签,因此 TAGPOST.post 和 TAGPOST.tag 对必须始终是唯一的。通常,我会通过在表中创建一个复合主键对来实现这一点,负责存储 TAGPOST 对象。

据我所知,没有办法表达这个唯一的约束。我已经标记了jpa.ddl=update,这意味着每次我将应用程序移动到新环境时,我都必须在数据库中手动修复此问题。这非常不方便,并且容易出错,尤其是在单元测试时,因为这样在每次迭代中都会或多或少地创建和删除数据库。

我什至想在@PrePersist上手动进行检查,甚至将检查移到业务层中,例如创建一个PostService。

我该怎么办?我是否缺少 Play 默认提供的功能?一些巧妙的注释来表达 TAGPOST 类的 @ManyToOne 属性的唯一性?

仅供引用:我使用的是 Play 1.2.5

编辑:TAGPOST 类如下所示:

@Entity
public class TagPost extends Model {

@ManyToOne
public Tag tag;

@ManyToOne
public Post post;

public Date dateAdded;

...
}

最佳答案

我编写了一个自定义Check来检查数据库的唯一性。也许您应该自定义它。

DBUnique.java

package models.check;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import net.sf.oval.configuration.annotation.Constraint;
import play.db.jpa.GenericModel;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Constraint(checkWith = DbUniqueCheck.class)
public @interface DBUnique {
String message() default DbUniqueCheck.mes;

Class<? extends GenericModel> modelClass();

String field() default ""; // field name will be used
}

DbUniqueCheck.java

package models.check;


import net.sf.oval.Validator;
import net.sf.oval.configuration.annotation.AbstractAnnotationCheck;
import net.sf.oval.context.FieldContext;
import net.sf.oval.context.OValContext;

import org.apache.commons.lang.StringUtils;

import play.db.jpa.GenericModel.JPAQuery;

@SuppressWarnings("serial")
public class DbUniqueCheck extends AbstractAnnotationCheck<DBUnique> {

final static String mes = "validation.dbunique";
DBUnique dbUnique;

@Override
public void configure(DBUnique dBUnique) {
this.dbUnique = dBUnique;
setMessage(dBUnique.message());
}

public boolean isSatisfied(Object validatedObject, Object value, OValContext context, Validator validator) {
try {
String field = dbUnique.field();
if (field == null || field.isEmpty()) {
field = ((FieldContext) context).getField().getName();
}
JPAQuery q = (JPAQuery) dbUnique.modelClass().getMethod("find", String.class, Object[].class)
.invoke(null, "by" + StringUtils.capitalize(field), new Object[] { value });
return q.first() == null;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}

}

用法:link to gist

它只是检查给定实例的给定字段在数据库中是否唯一。也许你应该做一些像这样的东西..

关于java - 将一对 @ManyToOne 相关属性标记为唯一。可能的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15565876/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com