使用Hibernate和Spring Data JPA

时间:2017-06-21 17:59:08

标签: postgresql hibernate spring-data-jpa

我有一个包含bytea列(名为'pdf')的表,我不想总是选择它,特别是当我从数据库返回列表时,由于性能问题。

我在存储库中使用弹出数据的本机查询来解决这些类型的情况之前(当我使用eclipselink时),但是对于Hibernate,如果我不写查询中的所有列,它会抛出异常。 / p>

出于测试目的,我试图仅从用户中选择 id ,我仍然得到例外。

示例:“SELET user.id FROM user WHERE user.id ='1'”

它抛出一个异常,说它在ResultSet中找不到 name ,如果我在SQL中放入 name ,那么它会显示 age 找不到,依此类推,直到我必须在SQL中写下所有列。

提前感谢您的帮助。

我已尝试过的内容

  • 在没有运气的情况下更新/降级Hibernate和Spring数据。
  • 仅使用我需要的列创建一个新实体,但是对我来说这是一个混乱的解决方案。

也许问题是我使用的框架和我使用它们的方式的组合,如果有人想要,我可以尝试上传我的整个项目结构。

我的代码实体

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

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;

@Column(name = "pdf")
private byte[] pdf;

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

@Column(name = "age")
private Integer age;

public User() {
}

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public byte[] getPdf() {
    return pdf;
}

public void setPdf(byte[] pdf) {
    this.pdf = pdf;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Integer getAge() {
    return age;
}

public void setAge(Integer age) {
    this.age = age;
}    

@Override
public int hashCode() {
    int hash = 0;
    hash += (id != null ? id.hashCode() : 0);
    return hash;
}

@Override
public boolean equals(Object object) {
    // TODO: Warning - this method won't work in the case the id fields are not set
    if (!(object instanceof Anexo)) {
        return false;
    }
    Anexo other = (Anexo) object;
    if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
        return false;
    }
    return true;
}

@Override
public String toString() {
    return "br.gov.to.secad.portal.domain.User[ id=" + id + " ]";
}

}

服务

@Service
@Transactional(readOnly = true)
public class UserService implements Serializable {

private static final long serialVersionUID = 1L;

@Autowired
private IUserRepository userRepository;


public UserService() {
}


public User findOne() {
    return userRepository.findOneSQL();
}

}

存储库

public interface IUserRepository extends JpaRepository<User, Serializable>, JpaSpecificationExecutor {

@Query(value = "SELECT user.id FROM user WHERE user.id = '1'", nativeQuery = true)
public User findOneSQL();

}

例外:

org.postgresql.util.PSQLException: The column name name was not found in this ResultSet.

解决方案

当我想要选择少于我在Entity类上映射的内容时,解决方案是使用Object数组,这就是我现在理解的Hibernate的限制。

基本上,该方法将返回Object [],然后我可以迭代每个位置并使用这些值实例化User的新实体。

示例:

@Query(value = "SELECT user.id FROM user WHERE user.id = '1'", nativeQuery = true)
public Object[] findOneSQL();

2 个答案:

答案 0 :(得分:0)

我遇到了同样的问题,我知道已经很晚了,但是有一种解决方案我觉得很优雅。

通过Spring documentation,您可以声明一个接口,并从此处获取所需的字段,在我的情况下,它类似于此。

用于最小化字段的界面:

from google.oauth2.credentials import Credentials

social_token = SocialToken.objects.get(account__user=request.user)
creds = Credentials(token=social_token.token,
                    refresh_token=social_token.token_secret,
                    client_id=social_token.app.client_id,
                    client_secret=social_token.app.secret)
service = build('calendar', 'v3', credentials=creds)
calendar = service.calendars().get(calendarId='primary').execute()

还有我的JpaRepository

public interface CountryMinify {
   String getName();
   String getNameTranslation();
}

请记住,列的名称应与gos getter相同。例如:column name_country-> AS名称,接口的getter是getName()

答案 1 :(得分:-1)

试试这个

@Query(value = "SELECT user.id FROM user WHERE user.id = '1'", nativeQuery = true)
Integer findOneSQL();

像这样调用方法

Integer user = userRepository.findOneSQL();

修改1:

由于您使用的是本机查询,因此无法使用Projections,这是访问某些实体字段的绝佳方式。有一个JIRA ticket仍在调查中。

<强>解决方案

从您的存储库返回列表,如此

@Query(value = "SELECT user.id, user.name  FROM user WHERE user.id = '1'", nativeQuery = true)
List<Object[]> findOneSQL();

迭代对象列表并获取特定列。

List<Object[]> userNative = userRepository.findOneSQL();
for (Object[] obj : userNative) {
    System.out.println("User id : " + obj[0]);
    System.out.println("User Name : " + obj[1]);
}