JPA(Java Persistence API)是 Sun 官方提出的 Java 持久化规范。它为 Java 开发人员提供了一种对象/关联映射工具来管理 Java 应用中的关系数据。它的出现主要是为了简化现有的持久化开发工作和整合 ORM 技术,结束现在 Hibernate、TopLink、JDO 等 ORM 框架各自为营的局面。值得注意的是,JPA 是在充分吸收了现有 Hibernate、TopLink、JDO 等 ORM 框架的基础上发展而来的,具有易于使用、伸缩性强等优点。
注意:JPA 是一套规范,不是一套产品,那么像 Hibernate、TopLink、JDO 它们是一套产品,如果说这些产品实现了这个 JPA 规范,那么就可以叫它们为 JPA 的实现产品。
mybatis自定义sql,比较灵活,也可以写复杂的sql,JPA只适合简单的单表sql
总结:mybatis和JPA各有优势,如果sql简单,则jpa使用效率更高,如果sql较复杂,需要自定义,则使用mybatis更加顺手。
< dependency > < groupId > org.Springframework.boot </ groupId > < artifactId > Spring-boot-starter-data-jpa </ artifactId > </ dependency > < dependency > < groupId > mysql </ groupId > < artifactId > mysql-connector-java </ artifactId > </ dependency >
spring: profiles:
active: dev
datasource:
driver-class-name: com .mysql .jdbc .Driver url: jdbc:mysql:// 127.0 .0 .1 : 3306 /soil
username: lxtest
password: admin jpa: hibernate:
ddl-auto: update
show-sql: true
注意: 我是用的是yml的语法,注意空格的长度,show-sql是在jpa下面的,不是hibernate.show-sql>
重点关注下 ddl-auto
这个配置项:
create:每次加载 hibernate 时都会删除上一次的生成的表,然后根据 model 类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
create-drop:每次加载 hibernate 时根据 model 类生成表,但是 sessionFactory 一关闭,表就自动删除。
update:最常用的属性,第一次加载 hibernate 时根据 model 类会自动建立起表的结构(前提是先建立好数据库),以后加载 hibernate 时根据 model 类自动更新表结构,即使表结构改变了,但表中的行仍然存在,不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
validate:每次加载 hibernate 时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
@Entity @Data public class User { @Id @GeneratedValue private Integer id; private String name; private String pwd; private Integer age; public User (){}
}
public interface UserRepository extends JpaRepository < User , Integer >{ }
@GetMapping( value = "/users" , produces = { "application/json;charset=UTF-8" }) public List<User> userList (){ return userRepository.findAll();
}
Spring Data Jpa有个很赞的功能就是可以自动根据方法名去生成相应的简单sql,具体的方法名和sql如下:
例如:
User findByUserNameOrEmail( String username, String email);
Long countByUserName( String userName);
Long deleteById(Long id); //获得符合查询条件的前10条数据 List < Person > findFirst10ByName( String name); //获取符合查询条件的前30条数据 List < Person > findTop30ByName( String name);
具体的方法名和语句如下:
关键字 | 方法命名 | sql where字句 |
---|---|---|
And | findByNameAndPwd | where name= ? and pwd =? |
Or | findByNameOrSex | where name= ? or sex=? |
Is,Equals | findById,findByIdEquals | where id= ? |
Between | findByIdBetween | where id between ? and ? |
LessThan | findByIdLessThan | where id < ? |
LessThanEquals | findByIdLessThanEquals | where id <= ? |
GreaterThan | findByIdGreaterThan | where id > ? |
GreaterThanEquals | findByIdGreaterThanEquals | where id > = ? |
After | findByIdAfter | where id > ? |
Before | findByIdBefore | where id < ? |
IsNull | findByNameIsNull | where name is null |
isNotNull,NotNull | findByNameNotNull | where id= ? |
Like | findByNameLike | where name like ? |
NotLike | findByNameNotLike | where name not like ? |
StartingWith | findByNameStartingWith | where name like ‘?%’ |
EndingWith | findByNameEndingWith | where name like ‘%?’ |
Containing | findByNameContaining | where name like ‘%?%’ |
OrderBy | findByIdOrderByXDesc | where id=? order by x desc |
Not | findByNameNot | where name <> ? |
In | findByIdIn(Collection c) | where id in (?) |
NotIn | findByIdNotIn(Collection c) | where id not in (?) |
True | findByAaaTue | where aaa = true |
False | findByAaaFalse | where aaa = false |
IgnoreCase | findByNameIgnoreCase | where id= ? |
@ Query( "select u from User u" ) Page <User> findALL (Pageable pageable ); Page<User> findByNickName(String nickName, Pageable pageable) ;
Pageable 是 Spring 封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则。
@Test public void testPageQuery (){ int page= 1 ,size= 10 ;
Sort sort = new Sort(Direction.DESC, "id" );
Pageable pageable = new PageRequest(page, size, sort);
userRepository.findALL(pageable);
userRepository.findByNickName( "testName" , pageable);
}
User findFirstByOrderByLastnameAsc();
User findTopByOrderByAgeDesc();
Page<User> queryFirst10ByLastname( String lastname, Pageable pageable); List <User> findFirst10ByLastname( String lastname, Sort sort); List <User> findTop10ByLastname( String lastname, Pageable pageable);
在 SQL 的查询方法上面使用 @Query 注解,如涉及到删除和修改需要加上 @Modifying,也可以根据需要添加 @Transactional 对事物的支持,查询超时的设置等。
@Transactional(timeout = 15)
@Modifying
@Query(" update User set name= ? 1 where id = ? 2 ")
int modifyById(String name, Long id);
@Transactional
@Modifying
@Query(" delete from User where id = ? 1 ")
void deleteById(Long id);
@Query(" select u from User u where u.pwd= ? 1 ")
User findByPwd(String pwd);
再新建一个用户详情的实体类:
@Data @Entity public class UserInfo { @Id @GeneratedValue private Integer id; private Integer userId; private String address; private String tel;
}
再新建一个接口,用于接受连表查询结果。
/**
* @author : Aslan
* @version : v1.0
* @time : 2018-06-26 14:11
* @desc : 定义一个结果集的接口类,接口类的内容来自于用户表和用户详情表,用于接收连表查询后的结果
*/ public interface UserDetail { String getTel();
String getAddress();
String getName();
}
新建一个Repository,也就是类似于DAO。
public interface UserInfoRepository extends JpaRepository < UserInfo , Integer > { /**
* 特别注意这里的 SQL 是 HQL,需要写类的名和属性,不是数据库里面的字段名,若写错则会报错:
*
* 传入电话,查找用户信息
* @param tel
* @return */ @Query( "select u.name,d.address,d.tel from User u , UserInfo d " + "where u.id = d.userId and d.tel = ?1 " ) List <UserDetail> findUserInfo(String tel);
}
使用:
@GetMapping( value = "/testUserInfo" ) public void testUserInfo (){
List<UserDetail> userDetails = userInfoRepository.findUserInfo( "111" ); for (UserDetail detail: userDetails){
System. out .println( "name = " +detail.getName());
}
}
凌云 2018-10-08
寒江独钓 2019-06-25
凌云 2019-01-02
伍仔 2019-02-20
伍仔 2016-11-28
凌云 2018-10-15
凌云 2018-10-08
凌云 2018-10-23
凌云 2018-02-05
泡泡 2016-04-04