使用Native Query

时间:2017-03-19 23:58:28

标签: java spring jpa spring-boot spring-data

我的问题基于another post。如何使用本机查询实现相同的功能?本机查询不允许JPQL因此也不允许新实例。

我的POJO。

class Coordinates {

    private final BigDecimal latitude
    private final BigDecimal longitude

    ...
}

我的数据库表包含城市周边的坐标,因此有三列:city_name,纬度,经度。每个城市都包含许多(实际上很多)周边坐标,用于在Google地图中构建阴影区域。

我打算在该表上构建一个简单的本机查询,该查询应该返回一个坐标列表。

6 个答案:

答案 0 :(得分:12)

another post找到答案。基本上我使用了SqlResultSetMappingConstructorResult(没有其他办法解决),特别注意对所提到的帖子的接受答案的评论:你需要添加@NamedNativeQuery注释到使用过的interface AND 的实体会在实体的名称前添加.,否则无效。

示例:

@Entity
@Table(name = "grupo_setorial")
@SqlResultSetMapping(
        name = "mapeamentoDeQuadrantes",
        classes = {
                @ConstructorResult(
                        targetClass = Coordenada.class,
                        columns = {
                                @ColumnResult(name = "latitude"),
                                @ColumnResult(name = "longitude")
                        }
                )
        }
)
@NamedNativeQuery(
        name = "GrupoCensitario.obterPerimetroDosSetores",
        query = "SELECT latitude as latitude, longitude as longitude FROM coordenadas where id_setor IN (:setores)",
        resultSetMapping = "mapeamentoDeQuadrantes"
)
public class GrupoCensitario {

答案 1 :(得分:3)

这是https://jira.spring.io/browse/DATAJPA-980Here是一个展示此问题的项目。

@Query(value = "SELECT name AS name, age AS age FROM Person", nativeQuery = true)
List<PersonSummary> findAllProjectedNativeQuery();

它是在Hibernate 5.2.11附带的Spring Data JPA 2.0 GA(Kay)版本中修复的。

Spring Data 1.10.12(Ingalls)和1.11.8(Hopper)也解决了这个问题,但需要在Hibernate 5.2.11上运行才能正常工作。

答案 2 :(得分:2)

您必须使用属于JPA的sql result set mapping

答案 3 :(得分:0)

如果您使用的是spring-data的最新版本,并且还使用了Repositories,我个人认为Itsallas的答案将给出正确的解决方案。

我实际上现在尚未了解(Spring Data)Projections,需要一点时间来了解他在示例中显示的内容。

因此,我只想向Spring Data JPA - Reference Documentation添加链接,请看一下Projections chapter

  

Spring Data查询方法通常返回由存储库管理的聚合根的一个或多个实例。但是,有时可能需要根据这些类型的某些属性创建投影。 Spring Data允许对专用的返回类型进行建模,以更选择性地检索托管聚合的部分视图。

答案 4 :(得分:0)

我找到的答案:

import React, { Component } from 'react';
import { Text, FlatList,View, StyleSheet, TouchableOpacity, Image} from 'react-native';
import { connect } from 'react-redux';
import {fetchPosts,likePost} from '../../actions'
import {Card} from '../Card';
import Icon from 'react-native-vector-icons/FontAwesome'


class PostScreen2 extends Component {
    constructor(props){
        super(props)
        this.onPressed = this.onPressed.bind(this)
    }

    shouldComponentUpdate(nextProp, nextState){
        console.log("Should component update")
        return true
    }

    componentDidMount(){
        const {id} = this.props
        console.log("ID'miz: ", id)
        this.props.fetchPosts(id)
    }

    componentDidUpdate(){
        console.log("Component did update.")
    }

    onPressed(postID){
        this.props.likePost(postID,this.props.id)
    }

    renderItem({item}){
        return(
            <Card>
                <View style={{flexDirection:'column',position:'absolute', justifyContent:'space-between'}}>
                    <View style={styles.topWrapper}>
                        <View style={styles.imageWrapper}>
                            <Image source={require('../../images/cat.png')}></Image>
                        </View>
                    <View style={styles.infoWrapper}>
                        <Text style={styles.nameWrapper}>{item.author_name}</Text>
                        <Text style={{fontSize:14}}>{item.date}</Text>
                    </View>
                </View>
                <View style={styles.contentWrapper}>
                    <Text style={{fontSize:20}}>{item.content}</Text>
                </View>
                    <View styles={styles.likeWrapper}>
                        <Text style={{marginLeft:10, fontSize:18, fontWeight:'bold'}}>{item.likes} likes</Text>
                    </View>
                    <TouchableOpacity onPress={() => {this.onPressed(item.id)}}>
                        <Icon style={{marginLeft:10}} size={25} name='star-o' />
                    </TouchableOpacity>
                </View>
            </Card>         
        )        
    }

    render() {
        const {posts} = this.props
        return (
            <FlatList
            data={posts}
            renderItem={this.renderItem}
        />
        );
    }
}


const mapStateToProps = state => {
    var posts = []
    for (var property in state.posts.data) {
      posts = state.posts.data[property]
    }

    return {
        posts,
        id: state.id
    }
}

const styles = StyleSheet.create({
    titleWrapper:{
        fontSize: 16,
        color: 'black'
    },
    authorWrapper: {
        fontSize: 14,
        color: 'gray'
    },
    descriptionWrapper: {
        marginLeft: 10,
        marginRight: 10,
        fontSize: 13,
        color: 'gray'
    },
    imageWrapper: {
        marginLeft: 10,
        marginTop: 10
    },
    nameWrapper: {
      fontWeight: 'bold',
      fontSize: 20
    },
    infoWrapper:{
      marginLeft: 10,
      marginTop: 10
    },
    topWrapper:{
      flex: 1,
      flexDirection: 'row'
    },
    contentWrapper: {
      marginLeft: 10,
      marginRight: 10,
    },
    likeWrapper: {
      fontSize: 18,
      fontWeight: 'bold'
    }
})


export default connect(mapStateToProps, {fetchPosts,likePost})(PostScreen2);

这样,我们返回Long列表-ID列表。这里的关键是我们将nativeQuery属性设置为true。值本身就是我们要执行的查询。

我希望能有所帮助。似乎是一个明确的解决方案。

答案 5 :(得分:-1)

投影解决方案是最好的。 (通过id查询只是一个例子,你可以使用extends CRUD操作)

只需添加接口作为对查询的响应

@Query(select * from tableA where tableA = :id)
MyInterface findTableAbyId(@Param(value = "id") Long id)

public interface MyInterface () {
    String getName();
    String getLastName();
    ......
}