具有@OneToOne关系的JPA规范

4

我希望使用jpa repository和规范。

现在我有两个表格。

@Entity
@Table(name="user")
public class User implements Serializable {

private static final long serialVersionUID = 1L;

private Long idUser;

private Area area;

@Id @GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="iduser")
public Long getIdUser() {
return idUser;
}
public void setIdUser(Long idUser) {
this.idUser = idUser;
}

@OneToOne(fetch=FetchType.LAZY)
@JoinColumn(name="idarea")
public Area getArea() {
    return area;
}

public void setArea(Area area) {
    this.area = area;
}

}

区域表格
@Entity
@Table(name = "area")
public class Area {

@Id @GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="idarea")
private Long idArea;

@Column(name="area_name")
private String areaName;

public Long getIdArea() {
    return idArea;
}

public void setIdArea(Long idArea) {
    this.idArea = idArea;
}

public String getAreaName() {
    return areaName;
}

public void setAreaName(String areaName) {
    this.areaName = areaName;
}

}

接下来我有一个用户仓库,它也扩展了JpaSpecificationExecutor

public interface UserRepository extends   CrudRepository<User,Long>,JpaSpecificationExecutor<User> {
}

最后我有一个简单的规范。

public class UserSpecification {

public static Specification<User> findByAreaName(final String areaName){
    return new Specification<User>() {

        @Override
        public Predicate toPredicate(Root<User> root,
                CriteriaQuery<?> criteria, CriteriaBuilder cb) {
            return cb.equal(root.<String>get("??????"),areaName);
        }
    };

}

}

所以,我的问题是:在表格区域中,我需要放入什么内容来代替“?????”?
1个回答

8
你可以尝试一下:

return cb.equal((Path<String>) ((Path<Area>) root.get("area")).get("areaName"),areaName);

你需要确保Area被加载,因为它是懒加载的。

编辑: 正如我在评论中提到的那样,也许可以尝试不使用任何转换。

我有一个针对这种情况的方法,你可以根据自己的需求进行调整:

@SuppressWarnings("unchecked")
private <T, R> Path<R> getPath(Class<R> resultType, Path<T> root, String path) {
    String[] pathElements = path.split("\\.");
    Path<?> retVal = root;
    for (String pathEl : pathElements) {
        retVal = (Path<R>) retVal.get(pathEl);
    }
    return (Path<R>) retVal;
}

使用点符号调用以获取路径。在您的情况下,应该这样写:

getPath(String.class, root, "area.areaName");

希望这可以帮助你!

1
也许可以尝试不进行强制类型转换:返回 cb.equal(root.get("area").get("areaName"), areaName); - Christian
日志显示 org.hibernate.type.SerializationException: could not deserialize,现在我正在尝试使用静态元模型 链接。你觉得怎么样? - Shinigami
静态元模型肯定比动态路径表达式更容易。我使用一个 Eclipse 插件来执行这些的生成。但也许你的 Area 类也应该是可序列化的。 - Christian
谢谢!您能否简要说明一下,您的SerializationException的原因是什么? - Christian
不,我不明白。我发现只有在特定情况下才会抛出异常。如果您能看一下,我在此链接exception中发布了部分日志。 - Shinigami
不起作用! - ⵔⴰⴼⵉⵇ ⴱⵓⵖⴰⵏⵉ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接