java web spring jpa 在以接口为dao的方法里使用原生sql,联合查找没有对应实体,用啥来接收? 求大神
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java web spring jpa 在以接口为dao的方法里使用原生sql,联合查找没有对应实体,用啥来接收? 求大神相关的知识,希望对你有一定的参考价值。
联合查找 返回的结果没有对应实体(对应数据库表的实体)
参考技术A 可以写一个实体类,实体类里写查询到的字段!追问我需要的实体类不与数据库表对应,没事吗?
追答用的是几个表连接吧?但是sql语句中的表名必须是数据库中的表名,不能使实体类名,就行了,很省事
参考技术B MAPmap.put
map.get 保持名称一样追问
dao继承repository接口,里面泛型写什么
参考技术C object的数组追问dao继承repository接口,里面泛型写什么
追答就写Object[]啊
追问泛型不与数据库表对应没事吗?
我自己创个类 (不与数据库对应)接收,可以吗?
追答确切的说是 List list里面装的object[]
如果sql 查询出来的是
name age
小李 12
小王 20
小刘 5
则 list 中 有三条记录
每条记录都是 object[]
如list中的第一个元素 是一个object[]
object[0] = 小李
object[1] = 12
集成Spring Data JPA
3.1 Spring Data JPA介绍
3.1.1 Spring Data JPA介绍
3.1.2 核心接口Repository
package org.springframework.data.repository;
import java.io.Serializable;
public interface Repository<T, ID extends Serializable> {
}
public interface JpaRepository extends PagingAndSortingRepository<T, ID> {
List<T> findAll();
List<T> findAll(Sort var1);
List<T> findAll(Iterable<ID> var1);
<S extends T> List<S> save(Iterable<S> var1);
void flush();
<S extends T> S saveAndFlush(S var1);
void deleteInBatch(Iterable<T> var1);
void deleteAllInBatch();
T getOne(ID var1);
<S extends T> List<S> findAll(Example<S> var1);
<S extends T> List<S> findAll(Example<S> var1, Sort var2);
}·
@NoRepositoryBean:使用该注解表明,此接口不是一个Repository Bean。
3.1.3 接口继承关系图
图3-1 Repository接口间集成关系
3.2 集成Spring Data JPA
3.2.1 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
图3-2 Maven Helper查看pom依赖包
图3-3 my-spring-boot项目目录
3.2.2 继承JpaRepository
/**
* 描述:用户Repository
* @author 阿毅
* @date 2017/10/14.
*/
public interface AyUserRepository extends JpaRepository<AyUser,String>{
}
/**
* 描述:用户表
* @Author 阿毅
* @date 2017/10/8.
*/
"ay_user") (name =
public class AyUser {
//主键
private String id;
//用户名
private String name;
//密码
private String password;
}
@Entity:每个持久化POJO类都是一个实体Bean, 通过在类的定义中使用 @Entity 注解来进行声明。
@Table:声明此对象映射到数据库的数据表。该注释不是必须的,如果没有则系统使用默认值(实体的短类名)。
@Id:指定表的主键。
3.2.3 服务层类实现
/**
* 描述:用户服务层接口
* @author 阿毅
* @date 2017/10/14
*/
public interface AyUserService {
AyUser findById(String id);
List<AyUser> findAll();
AyUser save(AyUser ayUser);
void delete(String id);
}
/**
* 描述:用户服务层实现类
* @author 阿毅
* @date 2017/10/14
*/
public class AyUserServiceImpl implements AyUserService{
private AyUserRepository ayUserRepository;
public AyUser findById(String id){
return ayUserRepository.findById(id).get();
}
public List<AyUser> findAll() {
return ayUserRepository.findAll();
}
public AyUser save(AyUser ayUser) {
return ayUserRepository.save(ayUser);
}
public void delete(String id) {
ayUserRepository.deleteById(id);
}
}
@ Service:Spring Boot会自动扫描到@Component注解的类,并把这些类纳入进Spring容器中管理。也可以用@Component注解,只是@Service注解更能表明该类是服务层类。
@Component:泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
@Repository:持久层组件,用于标注数据访问组件,即DAO组件 。
@Resource:这个注解属于J2EE的,默认安照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行查找。如果注解写在setter方法上默认取属性名进行装配。 当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。具体代码如下:
@Resource(name = "ayUserRepository")
private AyUserRepository ayUserRepository;
@Autowired:这个注解是属于Spring的,默认按类型装配。默认情况下要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用。具体代码如下:
private AyUserRepository ayUserRepository;
3.2.4 增删改查分页简单实现
上一节,我们已经在服务层类AyUserService开发完增删改查方法。这一节,我们将继续在类中添加分页接口,具体代码如下:
/**
* 描述:用户服务层接口
* @author 阿毅
* @date 2017/10/14
*/
public interface AyUserService {
AyUser findById(String id);
List<AyUser> findAll();
AyUser save(AyUser ayUser);
void delete(String id);
//分页
Page<AyUser> findAll(Pageable pageable);
}
Pageable:这是一个分页接口,查询时候我们只需要传入一个 Pageable接口的实现类,指定pageNumber和pageSize即可。pageNumber为第几页,而pageSize为每页大小。
Page:分页查询结果会封装在该类中,Page接口实现Slice接口,通过查看其源码可知。我们通过调用getTotalPages和 getContent等方法,可以方便获得总页数和查询的记录。Page接口和Slice接口源码如下:
public interface Page<T> extends Slice<T> {
int getTotalPages();
long getTotalElements();
<S> Page<S> map(Converter<? super T, ? extends S> var1);
}
public interface Slice<T> extends Iterable<T> {
int getNumber();
int getSize();
int getNumberOfElements();
List<T> getContent();
boolean hasContent();
Sort getSort();
boolean isFirst();
boolean isLast();
boolean hasNext();
boolean hasPrevious();
Pageable nextPageable();
Pageable previousPageable();
<S> Slice<S> map(Converter<? super T, ? extends S> var1);
}
分页方法定义好之后,我们在类AyUserServiceImpl中实现该方法,具体代码如下:
public Page<AyUser> findAll(Pageable pageable) {
return ayUserRepository.findAll(pageable);
}
3.2.5 自定义查询方法
/**
* 描述:用户Repository
* @author 阿毅
* @date 2017/10/14.
*/
public interface AyUserRepository extends JpaRepository<AyUser,String>{
/**
* 描述:通过名字相等查询,参数为 name
* 相当于:select u from ay_user u where u.name = ?1
*/
List<AyUser> findByName(String name);
/**
* 描述:通过名字like查询,参数为 name
* 相当于:select u from ay_user u where u.name like ?1
*/
List<AyUser> findByNameLike(String name);
/**
* 描述:通过主键id集合查询,参数为 id集合
* 相当于:select u from ay_user u where id in(?,?,?)
* @param ids
*/
List<AyUser> findByIdIn(Collection<String> ids);
}
在AyUserRepository中,我们自定义了3个查询的方法。从代码可以看出,Spring Data JPA为我们约定了一系列的规范,只要我们按照规范编写代码,Spring Data JPA就会根据代码翻译成相关的SQL语句,进行数据库查询。比如我们可以使用findBy、Like、In等关键字。其中findBy可以用read、readBy、query、queryBy、get、getBy来代替。关于查询关键字的更多内容,大家可以到官网(https://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/)查看,里面有详细的内容介绍,这里就不一一列举了。
AyUserRepository类中自定义查询方法开发完成之后,我们分别在类AyUserService和类AyUserServiceImpl中调用它们。
AyUserService继续添加这3个方法,具体代码如下:
List<AyUser> findByName(String name);
List<AyUser> findByNameLike(String name);
List<AyUser> findByIdIn(Collection<String> ids);
public List<AyUser> findByName(String name){
return ayUserRepository.findByName(name);
}
public List<AyUser> findByNameLike(String name){
return ayUserRepository.findByNameLike(name);
}
public List<AyUser> findByIdIn(Collection<String> ids){
return ayUserRepository.findByIdIn(ids);
}
提示:@Override注解不可去掉哦,它帮助我们校验接口方法是否被误改。
3.3 集成测试
3.3.1 测试用例开发
我们在测试类MySpringBootApplicationTests中添加如下代码:
@Resource
private AyUserService ayUserService;
@Test
public void testRepository(){
//查询所有数据
List<AyUser> userList = ayUserService.findAll();
System.out.println("findAll() :" + userList.size());
//通过name查询数据
List<AyUser> userList2 = ayUserService.findByName("阿毅");
System.out.println("findByName() :" + userList2.size());
Assert.isTrue(userList2.get(0).getName().equals("阿毅"),"data error!");
//通过name模糊查询数据
List<AyUser> userList3 = ayUserService.findByNameLike("%毅%");
System.out.println("findByNameLike() :" + userList3.size());
Assert.isTrue(userList3.get(0).getName().equals("阿毅"),"data error!");
//通过id列表查询数据
List<String> ids = new ArrayList<String>();
ids.add("1");
ids.add("2");
List<AyUser> userList4 = ayUserService.findByIdIn(ids);
System.out.println("findByIdIn() :" + userList4.size());
//分页查询数据
PageRequest pageRequest = new PageRequest(0,10);
Page<AyUser> userList5 = ayUserService.findAll(pageRequest);
System.out.println("page findAll():" + userList5.getTotalPages() + "/" + userList5.getSize());
//新增数据
AyUser ayUser = new AyUser();
ayUser.setId("3");
ayUser.setName("test");
ayUser.setPassword("123");
ayUserService.save(ayUser);
//删除数据
ayUserService.delete("3");
}
Assert:添加Assert断言,在软件开发中是一种常用的调试方式。从理论上来说,通过Assert断言方式可以证明程序的正确性。在现在项目中被广泛使用,这是大家需要掌握的基本知识。Assert提供了很多好用的方法,比如isNull,isTrue等。
3.3.2 测试
2 :
1 :
1 :
2 :
page findAll():1/10
以上是关于java web spring jpa 在以接口为dao的方法里使用原生sql,联合查找没有对应实体,用啥来接收? 求大神的主要内容,如果未能解决你的问题,请参考以下文章
Spring Data JPA:InvalidDataAccessApiUsageException:参数值 [web] 与预期类型不匹配 [java.util.Collection (n/a)];