WEB框架
有没有用过JPA,他支持的查询方式有哪些。复杂查询如何做。
Predicate+Join
1.定义查询方法:findByUsername,查询动词、主题、断言
2.声明自定义查询中
@Query(“select s from Spitter s where s. email like ‘%gmail. com’”)
List findAllGmailSpittesrs();
3.混合自定义的功能
EntityManager
JPA支持的查询方式有哪些。复杂查询如何做。
Predicate+Join
1.定义查询方法:findByUsername,查询动词、主题、断言
2.声明自定义查询中
@Query(“select s from Spitter s where s. email like ‘%gmail. com’”)
List findAllGmailSpittesrs();
3.混合自定义的功能
EntityManager
讲讲 Web 应用程序中的 Cookie 和 Session 是什么关系?
互联网应用大部分属于 Web 应用,开发人员或多或少会开发 Web 应用,而 Web 应用开发中一个很基本的问题是理解 Cookie 和 Session。有很多候选人简历中写精通 Web 开发,我就会问他们 Cookie 和 Session 是啥关系?实际上比较遗憾,真正能回答清楚的并不多。
这个问题需要一些底层 HTTP 协议知识,理解 HTTP 是无状态协议,理解服务端和客户端会话存储机制。对于能回答清楚的,
我会进一步扩展,Session 可以存储在哪些地方?客户端?服务器端?缓存?还有数据库?这些存储机制有何利弊?
粘性会话(sticky session)是什么意思?如何实现粘性会话?
分布式会话如何实现?诸如此类,全面考查候选人 Web 应用开发和分布式架构的实战经验。
session和cookie有什么区别
Session和Cookie的区别和联系以及Session的实现原理
1、session保存在服务器,客户端不知道其中的信息;cookie保存在客户端,服务器能够知道其中的信息。
2、session中保存的是对象,cookie中保存的是字符串。
3、session不能区分路径,同一个用户在访问一个网站期间,所有的session在任何一个地方都可以访问到。而cookie中如果设置了路径参数,那么同一个网站中不同路径下的cookie互相是访问不到的。
4、session需要借助cookie才能正常工作。如果客户端完全禁止cookie,session将失效。
http是无状态的协议,客户每次读取web页面时,服务器都打开新的会话,而且服务器也不会自动维护客户的上下文信息,那么要怎么才能实现网上商店中的购物车呢,session就是一种保存上下文信息的机制,它是针对每一个用户的,变量的值保存在服务器端,通过SessionID来区分不同的客户,session是以cookie或URL重写为基础的,默认使用cookie来实现,系统会创造一个名为JSESSIONID的输出cookie,我们叫做session cookie,以区别persistent cookies,也就是我们通常所说的cookie,注意session cookie是存储于浏览器内存中的,并不是写到硬盘上的,这也就是我们刚才看到的JSESSIONID,我们通常情是看不到JSESSIONID的,但是当我们把浏览器的cookie禁止后,web服务器会采用URL重写的方式传递Sessionid,我们就可以在地址栏看到 sessionid=KWJHUG6JJM65HS2K6之类的字符串。
明白了原理,我们就可以很容易的分辨出persistent cookies和session cookie的区别了,网上那些关于两者安全性的讨论也就一目了然了,session cookie针对某一次会话而言,会话结束session cookie也就随着消失了,而persistent cookie只是存在于客户端硬盘上的一段文本(通常是加密的),而且可能会遭到cookie欺骗以及针对cookie的跨站脚本攻击,自然不如 session cookie安全了。
通常session cookie是不能跨窗口使用的,当你新开了一个浏览器窗口进入相同页面时,系统会赋予你一个新的sessionid,这样我们信息共享的目的就达不到了,此时我们可以先把sessionid保存在persistent cookie中,然后在新窗口中读出来,就可以得到上一个窗口SessionID了,这样通过session cookie和persistent cookie的结合我们就实现了跨窗口的session tracking(会话跟踪)。
在一些web开发的书中,往往只是简单的把Session和cookie作为两种并列的http传送信息的方式,session cookies位于服务器端,persistent cookie位于客户端,可是session又是以cookie为基础的,明白的两者之间的联系和区别,我们就不难选择合适的技术来开发web service了。
简单介绍一下安全框架Shiro
核心概念
1.Subject
subject 被Shiro描述为一个主体,对于web应用来说,可以简单理解为用户。
2.SecurityManager
Subject 的幕后推手是SecurityManager,Subject 代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
3.Realm
Realm 充当了 Shiro 与应用安全数据间的“桥梁”或者“连接器”。当切实与像用户帐户这类安全相关数据进行交互,执行认证(登录)和授权(访问控制)时,Shiro 会从应用配置的 Realm 中查找很多内容。
Spring Data JPA参考实现
JPA中通过@Query注解使用原生sql语句执行数据库操作时候, in 条件的应用
@Modifying
@Query(value = "DELETE FROM HOME_ROLE_APARTMENT WHERE ROLE_SID = ?1 AND APARTMENT_SID IN ( ?2 )", nativeQuery = true)
@Transactional
public void deleteByRoleSidAndApartmentSid(String roleSid, List<String> apartmentSidList);
Spring Data JPA关系映射@OneToOne
@OneToOne, 表示一对一的映射关系,比如一个账号对应一个用户,一个实体用来描述账号的信息(账号,密码,账号是否可用,账号对应的角色等),另外一个实体用来描述用户的信息(昵称,年龄,性别,国籍等)。
该注解有六个属性:
public @interface OneToOne {
java.lang.Class targetEntity() default void.class;
javax.persistence.CascadeType[] cascade() default {};
javax.persistence.FetchType fetch() default javax.persistence.FetchType.EAGER;
boolean optional() default true;
java.lang.String mappedBy() default "";
boolean orphanRemoval() default false;
}
- targetEntity 关联目标实体类,指定类型后该属性可省略;
- cascade表示关联关系中的级联操作权限,有五种权限:
- CascadeType.PERSIST:级联新增(又称级联保存);
- CascadeType.MERGE:级联合并,更新该实体时,与其有映射关系的实体也跟随更新;
- CascadeType.REMOVE:级联删除,删除该实体时,与其有映射关系的实体也跟随删除;
- CascadeType.REFRESH:级联刷新,该实体被操作前都会刷新,保证数据合法性;
- CascadeType.ALL:包含以上四种级联操作;
- fetch数据加载策略,默认值为FetchType.EAGER:
- FetchType.LAZY 表示数据获取方式为懒加载;
- FetchType.EAGER 表示数据获取方式为急加载;
- optional 表示关联关系是否必须,当该值为true时,one的一方可以为null;
- mappedBy 指定映射关系由哪一方维护,一般使用在双向映射场景;
- orphanRemoval 孤值删除,将会删除孤立数据,外键为null的数据将被删除;
我们在使用的时候,通常为了保证表的简洁性,将主键共享,意思是用户的id和账号的id是一样的,不在表中单独存在一个字段用来描述关联关系;比如下面的例子:
首先创建一个账号实体
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
import javax.persistence.*;
@Table(name = "base_account")
@Entity
@org.hibernate.annotations.Table(appliesTo = "base_account", comment = "账号信息表")
public class AccountDO {
@Id
@GenericGenerator(name="idGenerator", strategy = "uuid")
@GeneratedValue(generator = "idGenerator")
@Column(name = "ACCOUNT_ID", length = 32)
private String accountId;
@Column(name = "USERNAME", columnDefinition = "VARCHAR(32) NOT NULL COMMENT '账号'")
private String username;
@Column(name = "PASSWORD", columnDefinition = "VARCHAR(128) NOT NULL COMMENT '密码'")
private String password;
@OneToOne(cascade = {CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.REFRESH})
@PrimaryKeyJoinColumn
private UserDO userDO;
// 省略构造函数,get/set方法,toString方法等
创建一个用户信息实体
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
import javax.persistence.*;
@Table(name = "base_user")
@Entity
@org.hibernate.annotations.Table(appliesTo = "base_user", comment = "用户信息表")
public class UserDO {
@Id
@GenericGenerator(name = "idGenerator", strategy = "foreign", parameters = @Parameter(name = "property", value = "accountDO"))
@GeneratedValue(generator = "idGenerator")
@Column(name = "USER_ID", length = 32)
private String userId;
@Column(name = "NICKNAME", columnDefinition = "VARCHAR(32) NOT NULL COMMENT '昵称'")
private String nickname;
@Column(name = "AGE", columnDefinition = "TINYINT DEFAULT NULL COMMENT '年龄'")
private Integer age;
@Column(name = "SEX", columnDefinition = "CHAR(2) DEFAULT NULL COMMENT '性别'")
private String sex;
@OneToOne(mappedBy = "userDO")
private AccountDO accountDO;
// 省略构造函数,get/set方法,toString方法等
用户实体的主键和账号实体的主键都使用一个生成策略,生成的id也一样,且在账号实体中使用@PrimaryKeyJoinColumn来声明在表中不建立对应的映射字段。
这里贴出源码,一个关系映射的小例子
原创不易,感谢支持。