java SSH学习

【【struts2】】
1、pom
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.5.18</version>
</dependency
<!–servlet、jsp–>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
<scope>runtime</scope>
</dependency>
2、web.xml
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3、核心配置文件struts.xml
<?xml version=“1.0” encoding=“UTF-8”?>
<!DOCTYPE struts PUBLIC
“-//Apache Software Foundation//DTD Struts Configuration 2.5//EN”
“http://struts.apache.org/dtds/struts-2.5.dtd”>
<struts>
<!–一些常量的配置,例如默认扩展名,默认字符集等–>
<constant name=“struts.action.extension” value=“action”/>
<constant name=“struts.i18n.encoding” value=“UTF-8”/>

&lt;!--package是最外层单元,通过namespace定义一组同一路径下的路由映射。比如/a1/b1;/a1/b2,都是同一个包下的不同路由
    name:同一项目下不同命即可,用来管理包
    extends:包可以继承,最顶层需要继承默认提供的struts-default
    namespace:共同的父路径,如果是/表示一级路径。下面的路由都是/xx形式的路径。
    abstract:定义抽象包,可供其他包继承
--&gt;
&lt;package name="basicstruts" extends="struts-default" namespace="/" &gt;
    &lt;!--action是执行路由映射的基本单元,一个aciton代表一个url和action.class的映射
        name:url的最底层路径,访问时默认加一个.action也可以访问到。
        class:处理的java类
        method:默认是execute,可以指定action类中默认执行的方法。
        result:返回jsp的定义,一般有success/error/input/login四种,input代表表单验证出错,login登陆出错,默认不填设置为success
        converter:设置类型转换器
    --&gt;
    &lt;action name="hello"  class="action.HelloAction" &gt;
        &lt;result name=""&gt;pages/success.jsp&lt;/result&gt;
    &lt;/action&gt;
&lt;/package&gt;

</struts>
4、编写action类
有三种方式
1、普通pojo类,手写public String execute()方法
2、实现action接口,有五个result常量可以用。
3、继承actionSupport类,推进该方式,有数据校验、国际化等一系列操作可以使用。
public class HelloAction extends ActionSupport {
@Override
public String execute(){
System.out.println(“hello 执行了!”);
return SUCCESS;
}
}

【路由映射细节】
1、struts2默认是一个url对应一个action,但可以通过指定method进行方法级url映射的配置。
<action name=“userfind” class="" method=“find”/>
<action name=“userupdate” class="" method=“update”/>
2、可以通过通配符方式,一条配置解决方法级映射。类似正则表达式,method中可以捕获前面name中匹配到的类容。
<action name="user_
" class="" method="{1}"/>
更抽象写法:
<action name="_" class=“xxx.{1}” method="{2}"/>
3、动态方法访问。允许直接通过actionname!方法名的方式直接访问方法。但是要先打开全局开关。
<constant name=“struts.enable.DynamicMethodInvocation” value=“true”/>
action中添加:<allowed-methods>login</allowed-methods>后,login方法就可以使用了"mylogin!login"

【原生servletapi访问】
1、解耦方式,action将对应结果做解封装,此时操作的都是action封装了第二道的map对象,只能操作域对象。
ActionContext actionContext = ActionContext.getContext();
HttpParameters parameters = actionContext.getParameters();//获取request中的传递参数
actionContext.put(“xx”,1);//request.add
actionContext.getSession().put(“xx”,1);//session.add
actionContext.getApplication().put(“xx”,1);//app.add
2、直接获取原生对象
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
3、接口注入的方式
public class ServletApiDemo extends ActionSupport implements ServletRequestAware{
private HttpServletRequest request;

@Override
public void setServletRequest(HttpServletRequest httpServletRequest) {
    this.request=httpServletRequest;
}

@Override
public String execute() throws Exception {
    return super.execute();
}

}

注意:servlet单例、action多例、springmvc controller单例。

【结果页面配置细节】
1、包级全局结果配置。当全局和局部都设置了同名结果时,局部会覆盖全局。
<global-results>
<result name=“success”>pages/success.jsp</result>
</global-results>
2、重定向和转发:
通过result的type参数指定:
dispatcher:默认值,请求转发(action转发到jsp)
redirect:重定向(action重定向jsp)
chain:action转发action
redirectAction:action重定向action。
stream:提供下载功能。

【数据封装】
1、在action中设置同名变量,并提供set方法,访问该aciton的任一方法时,框架会自动封装到类变量中。可以在方法内部访问使用。该种方法不能封装pojo类。
2、和1一样,但是在action中设置pojo类变量,并提供getset方法。页面中写类似springmvc的.表达式。访问该aciton的任一方法时,框架会自动封装到类变量中。可以在方法内部访问使用。
3、模型驱动方式,有缺点,只能同时封装一个数据。
public class Modeldemo extends ActionSupport implements ModelDriven<User> {
User user=new User();
@Override
public User getModel() {
return user;
}
}
4、list<bean>时,前端name写写list[0].name;list[0].money;list[1].name;list[1].money;myap<bean>也是同样的操作。

类型转换错误的处理:
默认会进行表单的数据类型验证,数据类型不对,会默认返回表单的input视图,如果没有配置该视图,就会报错。
在input视图中,可以通过<s:fielderror/>标签进行显示。
<%@taglib prefix=“s” uri="/struts-tags" %>
<s:fielderror/>

【表单校验】
1、手动效验。此时针对的是action中所有方法,若针对一个,方法名改成validateExceute形式即可。
@Override
public void validate() {
if(userName==null || userName.length()==0){
this.addFieldError(“userName”,“用户名不能为空!”);
}
}
2、xml配置方式。
1)在action包下创建一个action类名一样的-validation.xml文件。
2)若针对方法,需要新建类名-方法名-validation.xml文件。
<!DOCTYPE validators PUBLIC
“-//Apache Struts//XWork Validator 1.0.3//EN”
“http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd”>
<validators>
在 -validation.xml文件中有两种方式定义
<validator>
<field-validator>
非字段验证器: 元素允许你声明两种验证器 (普通 验证器和字段验证器):

<validator type="expression>
<param name=“expression”>foo gt bar</param>
<message>foo must be great than bar.</message>
</validator>

<validator type=“required”>
<param name=“fieldName”>bar</param>
<message>You must enter a value for bar.</message>
</validator>

字段验证器:
<field name=“email_address”>
<field-validator type=“required”>
<message>You cannot leave the email address field empty.</message>
</field-validator>
<field-validator type=“email”>
<message>The email address you entered is not valid.</message>
</field-validator>
</field>
required:必填校验器
requiredstring:必填字符串校验器
int:整数校验器
double:双精度浮点数校验器
date:日期校验器
expression:表达式校验器
fieldexpression:字段表达式校验器
email:电子邮件校验器
url:网址校验器
visitor:Visitor校验器
conversion:转换校验器
stringlength:字符串长度校验器
regex:正则表达式校验器

【ognl表达式】
ognl(对象图导航语言)
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>3.2.10</version>
</dependency>
ognl操作java类:
OgnlContext context=new OgnlContext();
Ognl.getvalue("",context,context.getRoot())
第一个参数就是表达式的具体形式。

表达式常用操作方法如下:
1、操作方法对象名.方法名如:“helloworld”.length()
2、操作静态方法@类名@方法名 @java.lang.math@random()
3、获取root对象域中的值,直接写属性名即可。
OgnlContext context=new OgnlContext();
Ognl.getvalue(“username”,context,context.getRoot(new User(“aaa”,1000)))
4、获取context对象域中的值,表达式需要加井号:#属性名。
OgnlContext context=new OgnlContext();
context.put(“name”,100)
Ognl.getvalue("#username",context,context.getRoot())

struts2已经默认引用了ognl的包,并且继承了jsp能够使用的标签:
<s:property value="‘helloword’.length()" />
需要注意的是,访问静态成员和静态方法时,需要打开全局开关。
<constant name=“struts.ognl.allowStaticMethodAccess” value=“true”/>

ognl在页面上制造list和集合:
<s:property value="‘helloword’.length()" />
<s:iterator value="{‘aa’,‘bb’,‘cc’,12}" var=“i”>
<s:property value=“i”/>
</s:iterator>

<s:iterator value="#{ ‘bb’:‘ff’,‘cc’:‘dd’}">
<s:property value=“key”/><s:property value=“value”/>
</s:iterator>

【值栈ValueStack】
一个请求发起时,一个action创建,此时同步创建一个valuestack,用于存储action和jsp通信的数据。显然,aciton和vs是一一对应的,都是多例对象。
可以发现,vs和reqeust域对象在作用上的类似的,但vs优势的地方在于,它可以在程序的任何地方取出,而不只是jsp页面。
vs中有两块主要区域:
root区:实际上就是一个arrayList,存储这一些pojo对象。
context区:实际上就是一个map,存储着一些域对象,例如:
root
request/session/application/parameterts/attr

<s:debug>标签可以在jsp输出vs的所有属性。

获取vs:
1、通过actioncontext获取:
ActionContext actionContext = ActionContext.getContext();
ValueStack valueStack = actionContext.getValueStack();
2、通过request获取:
HttpServletRequest request = ServletActionContext.getRequest();
ValueStack v = (ValueStack) request.getAttribute(ServletActionContext.VALUE_STACK);

向vs存值:
1、若action中有属性,且属性有get方法,那么action被存入vs之后,该属性也会被存入值栈。
2、调用vs.push(obj) vs.set(key,value)即可。最后放的对象会放到值栈顶端。

从vs取值:
1、获取root数据
push方法,obj就是作用域,直接写属性名
set方法,set的name是作用域,需要写name.xxx调用。放入的是list时,name[i].xxx调用。
2、获取context数据
#request.name
#session.user.name
需要带作用域进行查询,如果想执行类似el表达式的查找效果,可以写#attr.name

el访问vs的root区:
struts2对request.getattr方法进行了增强,当request中找不到时,会默认从vs中查找。
所以${username}能够获取到vs中的数据。

【拦截器】
1、自定义一个拦截器类,继承abstractInterceptor。重写string intercept(invocation)方法。方法参数invocation即相当于action中某个具体方法的引用。调用invocation.invoke(),即执行方法。
2、注册拦截器,有两种方式:
方式一,在package中定义,拦截某个具体action时,在aciton中引入。注意:使用自定义后,默认拦截器组失效。需要手动再配置进去。
<interceptors>
<interceptor name=“myIntercept” class=""/>
</interceptors>
<action name=“hello” class=“action.HelloAction” >
<result name="">pages/success.jsp</result>
<interceptor-ref name=“defaultStack”/>
<interceptor-ref name=“myIntercept”/>
</action>
方式二,使用<interceptor-stack>标签做一个拦截器栈,action中直接引入该拦截器栈即可。

【注解开发】
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-convention-plugin</artifactId>
<version>${struts.version}</version>
</dependency>
struts2框架提供了四个与Action相关的注解类型,分别为ParentPackage、Namespace、Result和Action。
ParentPackage(“struts-defaul”) value表示继承的包
Namespace:Namespace注解用于指定Action所在的包的命名空间。该注解只有一个value参数,用于指定ACtion所属于的命名空间。在为命名空间取名需要使用斜杠(/)开头
Result:Result注解用于定义一个Result映射,该注解包含四个参数,

1)name:可选参数,用于指定Result的逻辑名,默认值为success
2)location:必选参数,用于指定Result对应资源的URL
3)type:可选参数,用于指定Result的类型,默认值为NullResult.class
4)params:可选参数,用于为Result指定要传递的参数,格式为:{key1,value1,key2,value2,…}
5)exceptionMappings:可选参数,指定Action的异常处理类,他是一个Exception-Mapping的数组属性

【【hibernate】】
快速入门】:
maven:
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.10.Final</version>
</dependency>

映射文件:
<?xml version=“1.0” encoding=“utf-8”?>
<!DOCTYPE hibernate-mapping PUBLIC
“-//Hibernate/Hibernate Mapping DTD 3.0//EN”
“http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd”>
<hibernate-mapping>
<class name=“domain.Account” table=“account”>
<!–如果name和column完全一致,后者可以省略–>
<id name=“id” column=“id”>
<generator class=“native”/>
</id>
<property name=“name” column=“name”/>
<property name=“money” column=“money”/>
</class>
</hibernate-mapping>
property属性:
name :类中的属性名
column :表中的字段名
length :长度
type :类型
not-null :设置非空
unique :设置唯一

核心配置:
<?xml version=“1.0” encoding=“utf-8”?>
<!DOCTYPE hibernate-configuration PUBLIC
“-//Hibernate/Hibernate Configuration DTD 3.0//EN”
“http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd”>
<hibernate-configuration>
<session-factory>
<property name=“hibernate.connection.driver_class”>com.mysql.cj.jdbc.Driver</property>
<property name=“hibernate.connection.url”>jdbc:mysql://localhost:3306/test </property>
<property name=“hibernate.connection.username”>root</property>
<property name=“hibernate.connection.password”>JIANGkui1</property>
<property name=“hibernate.dialect”>org.hibernate.dialect.MySQLDialect</property>
<!–打印和格式化sql语句–>
<property name=“hibernate.show_sql”>true</property>
<property name=“hibernate.format_sql”>true</property>
<mapping resource=“domain/Account-orm.xml”/>
</session-factory>
</hibernate-configuration>
可选配置:
显示SQL :hibernate.show_sql
格式化SQL :hibernate.format_sql
自动建表 :hibernate.hbm2ddl.auto
none :不使用hibernate的自动建表
create :如果数据库中已经有表,删除原有表,重新创建,如果没有表,新建表。(测试)
create-drop :如果数据库中已经有表,删除原有表,执行操作,删除这个表。如果没有表,新建一个,使用完了删除该表。(测试)
*update:如果数据库中有表,使用原有表,如果没有表,创建新表(更新表结构)
*validate:如果没有表,不会创建表。只会使用数据库中原有的表。(校验映射和表结构)。
主键增长策略:
increment hibernate自增,线程不安全。
identity 数据库自增。DB2、MySQL、SQL Server、Sybase 和 HypersonicSQL 数据库中可以使用
sequence 数据库序列。oracle等。
hilo 使用一个高/低位算法高效地生成 long、short 或 int 类型的标识符。给定一个表和字段(默认的表和字段分别为 hibernate_unique_key 和 next_hi)作为高位值的来源。高/低位算法产生的标识符仅在特定数据库中是唯一的
native 自动选择identity、sequence、hilo 三种生成器中的一种,适合跨数据库平台开发,适用于代理主键
uuid 字符串形主键uuid
assigned 由java程序负责主键,hibernate放弃主键管理。

使用:
Configuration configuration=new Configuration().configure();//配置对象,通过它加载配置文件。
SessionFactory sessionFactory = configuration.buildSessionFactory();//sessionFactory对象,连接池对象,维护着连接池和二级缓存。一个项目最好只实例化一个factory。线程安全的。
session = sessionFactory.openSession();//session代表一个connect连接,它是非线程安全的,注意不要产生线程问题。
transaction = session.beginTransaction();

    Account account = new Account("hibernate", 888f,48);
    session.save(account);

    transaction.commit();
    session.close();

【基本api】
Session中的API、;
保存方法:
Serializable save(Object obj);
查询方法:
T get(Class c,Serializable id);
T load(Class c,Serializable id);//懒加载的get方法
void update(Object obj);
void delete(Object obj);
void saveOrUpdate(Object obj)
query session.createQurey(“hql”);//使用hql进行查询,可以自动封装数据
SQLquery session.createSQLQurey(“SQL”);//使用SQL进行查询,不能自动封装数据
query步骤:
获得 Hibernate Session 对象。
编写 HQL 语句。
调用 session.createQuery 创建查询对象。
如果 HQL 语句包含参数,则调用 Query 的 setXxx 设置参数。
调用 Query 对象的 list() 或 uniqueResult() 方法执行查询。
Query query = session.createQuery(“from Account where name like ?1”);
query.setParameter(1,“杨%”);
//Query query = session.createQuery(“from Account where name like :name”);
//query.setParameter(“name”,“杨%”);
query.setFirstResult(0);
query.setMaxResults(5);
List<Account> accounts = query.list();

【三态】
1)瞬时态(transient)未保存
瞬时态也称为临时态或者自由态,瞬时态的对象是由 new 关键字开辟内存空间的对象,不存在持久化标识 OID(相当于主键值),且未与任何的 Session 实例相关联,在数据库中也没有记录,失去引用后将被 JVM 回收。瞬时对象在内存孤立存在,它是携带信息的载体,不和数据库的数据有任何关联关系。
2)持久态(persistent)已保存
持久态的对象存在一个持久化标识 OID,当对象加入到 Session 缓存中时,就与 Session 实例相关联。它在数据库中存在与之对应的记录,每条记录只对应唯一的持久化对象。需要注意的是,持久态对象是在事务还未提交前变成持久态的。
3)脱管态(detached)已断线
脱管态也称离线态或者游离态,当持久化对象与 Session 断开时就变成了脱管态,但是脱管态依然存在持久化标识 OID,只是失去了与当前 Session 的关联。需要注意的是,脱管态对象发生改变时 Hibernate 是不能检测到的。

注意:持久化态的对象在commit时,会和缓存做比较,当内容发生变化时,会自动向数据库发送update的sql语句。

【一级缓存】
1、保存时默认将数据库返回的已持久化对象加入缓存(不会等提交,而是马上发sql)。
2、查询时先查缓存,缓存没有,才会查数据库并加入缓存。
3、session关闭时,缓存清空,clear()方法调用后,也将清空缓存,此后提交也不会再自动发更新语句。

刷出缓存(将缓存和快照的改变发送到数据库):
1、 commit()方法执行时,会进行保存内容和缓存的对比,智能发送update的sql语句。
2、select时,如果缓存中的对象已经发生变化,会更新缓存。
3、调用session.flush方法,会默认刷新缓存,强制将缓存与快照的变化更新的数据库。
3、调用.refresh方法,会重新查询数据库,用数据库值覆盖缓存。

【事务管理】
<property name=“hibernate.current_session_context_class”>thread</property>
开启session线程绑定,然后所有获取session 的地方都用:
session = sessionFactory.getCurrentSession();
保证一个线程获取的都是同一个session,即可完成事务管理。

【qbc】
通过criteriaQuery.where/from/orderby/gropyby来指定具体的语句
通过CriteriaBuilder.like/or/and来指定具体的条件。
// 获取工厂对象
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
// 获取针对某个表的条件对象,相当于指定返回值的封装类型
CriteriaQuery<Account> criteriaQuery = criteriaBuilder.createQuery(Account.class);
// 指定根条件,相当于写from语句
Root<Account> root = criteriaQuery.from(Account.class);
// 指定查询条件,相当于写where语句,多条件用工厂的and或or链接
Predicate equal1 = criteriaBuilder.like(root.<String>get(“name”),“杨%”);
Predicate lt1 = criteriaBuilder.gt(root.<Number>get(“money”), 1000);
criteriaQuery.where(criteriaBuilder.and(equal1,lt1));
// 指定排序
criteriaQuery.orderBy(criteriaBuilder.desc(root.get(“id”)), criteriaBuilder.asc(root.get(“userid”)));

// 使用session执行查询语句,与hql一致了
Query<Account> query = session.createQuery(criteriaQuery);
query.setFetchSize(0);
query.setMaxResults(5);
List<Account> accounts = query.list();

补充,旧版写法:
Configuration config = new Configuration().configure();
// 2.通过session获得Criteria对象
Criteria criteria = session.createCriteria(User.class);
// 3.使用Restrictions的eq方法设定查询条件为name=“zhangsan”
// 4.向Criteria对象中添加查询条件
criteria.add(Restrictions.eq(“name”, “zhangsan”));
// 5.执行Criterita的list()方法获得结果
List<User> list = criteria.list();

【多表关联】
多一方,主表:
<!–to-one标签,name属性名,class属性类型,column本表外键名称–>
<many-to-one name=“user” class=“domain.User” column=“userid” cascade=“save-update”/>

一一方,被关联表:
    &lt;!--集合配置,里面肯定都是to-many的标签,name属性名、class属性类、key.column是我方在对方表的外键,写上后可以操作其外键。--&gt;
    &lt;set name="accounts" cascade="save-update,delete"&gt;
        &lt;key column="userid"&gt;&lt;/key&gt;
        &lt;one-to-many class="domain.Account"/&gt;
    &lt;/set&gt;

一对多关系注意】:
1、<many-to-one>标签就相当于外键了,不可以同时进行该标签和外键值的映射,否则会创建两列userid。实体类中,set标签必须先被实例化,而且只能用set,不用能list容器。
2、一对多和多对一查询时都是1+n式查询,可以通过属性控制发送的类型。
3、保存时,需要注意被包含的所有级联对象都应该是持久化态的,设置了级联更新除外。保存时,注意只要有一方构建了关系即可,否则会发两遍修改外键的sql语句。
4、外键关联关系细节:保存时,如果由主表进行了外键关联,则只会发一个insert语句,将外键id一起insert。如果由附表进行外键关联,则会默认先新建主表主体内容,然后发一条update语句,将所有主表的外键id进行修改。注意,此时数据库需要允许外键可以为null,否则先新建主表时就会报错,外键id不能为null!
5、<many-to-one>标签上添加cascade=“save-update”,主表保存时,会默认将已关联的附表瞬时态对象进行保存。同样,在set标签上添加cascade,附表保存时,也默认将瞬时态的已关联多方主表对象进行保存。注意,只会将本对象包含的对象A进行保存,本对象被其他对象B关联,如果不保存其他对象B,并不会保存对象B和与B的外键关系。
5、删除被关联的附表时,hibernate默认将主表的外键id设置为null。如果在set上设置了cascade=“delete”,则删除附表时,所有被关联的多方主表都会被删除。注意,级联删除实际上不是根据数据库,而是缓存的,所以需要先查询,确认内部带着set关联时,才能级联删除。
6、默认情况下,to-one标签和 set标签都拥有外键管理权,如果想要一方放弃,设置inverse=true即可。通常逻辑下,外键由外键的物理表管理即可,也就是由多的主表管理即可,此时需要在一的附表set中设置inverse=true。

综上:设置时,一般<many-to-one cascade=“save-update”>、<set cascade=“save-update,delete” inverse=“true”>

多对多:
<!–和普通的一对多不同,这里的key.column是中间表中关联我方的外键。m2m中的c是对方的关联外键–>
user中:
<set name=“roles” table=“user_role”>
<key column=“uid”/>
<many-to-many class=“domain.Role” column=“rid”/>
</set>

role中:
    &lt;set name="users" table="user_role"&gt;
        &lt;key column="rid"&gt;&lt;/key&gt;
        &lt;many-to-many class="domain.User" column="uid"/&gt;
    &lt;/set&gt;

M2M注意事项】:
1、两边的表都有外键控制权,有外键控制权代表会在中间表发insert语句,此时如果两个类都做了set.add外键关联的操作,就会发送同一条insert语句,百分百报错。此时显然需要inverse,一般根据业务逻辑,在逻辑上被选择的那一方(比如用户和角色,角色就是被选择的一方)加上inverse=true。
2、m2m一般都配置级联保存或更新,但一般不需要配置级联删除,默认操作是删除主表,将中间表置为null即可。
3、多对多增加、修改、删除关系,完全靠集合操作即可完成。

关联查询发送sql语句细节】:
可以在to-one或set标签上设置fetch属性来修改发送的sql类型。
set标签(一找多反向查询):
select 发送select语句,一共发送N+1条,可以由lazy控制是否延迟发送。
join 发送join语句,一次性查询全部关联对象。没有N+1问题,lazy失效,只发送一条。
subselect 发送子查询select user where user.id in(select userid from account),可以由lazy控制,发送两条。
lazy属性用来修改是否延迟发送:
ture
false
extra 极其懒惰模式。查询个数时发count语句,具体查询到关联对象的属性时才查出来。
set标签一找多时,默认是select、true。如果业务要求每次都必须同时查询出来,可以配置成join

money-to-one标签(多找一正向查询);
fetch:
select:默认值
join

lazy:
proxy 默认值,默认使用set标签上的fetch值。
false 不采用延迟
no-proxy

batch-size】
可以通过set标签和set(配置一找多)标签所在类的class上(配置多找一)配置batch-size。
如果配置了它,那么关联查询时,就会采用lazy模式的subselect查询,且查询的id数量最多是它设置的值。会默认发送总数量/batch-size条sql子查询语句。

【HQL查询】
1、别名查询:
from Account a;select a from Account;
2、排序查询:
from User order by id,userName desc ;默认升序
3、条件查询:
Query query = session.createQuery(“from Account where name like ?1”);
query.setParameter(1,“杨%”);位置匹配
//Query query = session.createQuery(“from Account where name like :name”);
//query.setParameter(“name”,“杨%”);名字匹配
4、投影查询:
Query query = session.createQuery(“select u.userName,u.sex from User u”);
List<Object[]> list = query.list();
第二种,个别封装:
Query query = session.createQuery(“select new User (u.userName,u.birthday,u.sex) from User u”);
List<User> list = query.list();
5、分页查询
query.setFetchSize(0);
query.setMaxResults(5);
返回从1-5。公式为pagenum-1)pagesize,pagesize
6、聚合函数
Long re =(Long) session.createQuery("select count(
) from User ").uniqueResult();
List list = session.createQuery(“select count(distinct userName),address from User group by address”).list();

7、多表连接
内连接:
List<Object[]> list = session.createQuery(“from Account a inner join a.user”).list();注意,必须使用别名查询。 迫切内连接,封装成对象,会有封装重复问题
List<Account> list = session.createQuery(“from Account a inner join fetch a.user”).list();
select distinct a from Account a inner join fetch a.user 这样就没有封装重复问题了

【离线条件查询】
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(User.class);
detachedCriteria.add(Restrictions.like(“userName”,“杨%”));
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
List<User> list = criteria.list();

【sql查询】
NativeQuery sqlQuery = session.createSQLQuery(“select * from user”);
sqlQuery.addEntity(User.class);
List<User> list = sqlQuery.list();

【注解开发】
<mapping class=“domain.User”/>
<mapping class=“domain.Role”/>
<mapping class=“domain.Account”/>

@Entity 相当于class标签,指定当前类是一个实体类,name属性为实体名称。默认为类的非限定性类名,用于hql查询。
@Table name属性指定映射的表名。默认与实体名称相同。

@Id用在主键id属性上,或者其get方法上,表示当前属性将对应数据库中的主键。
@GeneratedValue 将指定主键值的来源,其属性strategy用于指定主键的生成策略。其值为系统定义好的四种策略之一。默认为AUTO(native)。尽量写@GeneratedValue(strategy = GenerationType.IDENTITY)不会报错。
@Column name/nullable/length/insertable/updateable
precision和scale表示精度,当字段类型为double时,precision表示数值的总长度,scale表示小数点所占的位数;
@Basic:表示该字段将映射到DB中,是属性的默认注解;
@Transient:表示该字段不映射到DB中,该注解无属性;
@Temporal(TemporalType.DATE) 指定输出日期的格式

表关联:
@OneToMany表明是一对多关联关系;属性如下:
targetEntity:指明该属性所关联的类。
cascade:指定级联类型。其为数组,使用多种级联,则可使用{}赋值。其值为Cascade常量。
mappedBy:string类型写对方表名,等价于inverse=true,放弃外键维护。使用该属性后将不能够再使用@JoinColumn注解。
fetch = FetchType.EAGER
@JoinColumn指明该属性所关联的外键;设置该属性后默认拥有外键维护权

@ManyToMany注解 其会自动生成一个中间表,表名为两个关联对象的映射表名的联合:表1_表2。只不过,谁在维护关联关系,谁的表名在前。字段名与谁在维护关联关系相关。谁在维护关联关系,谁的表名将出现在第一个字段名中,而该类的关联属性名将出现在第二个字段名中。字段名分别为表名_id与关联属性名_id。
@JoinTable 指定中间表的一些设置
name:中间表名称
joinColumns,本实体类在中间表的外键列名字,@JoinColumn(name = “studentId”)这样写。
inverseJoinColumns 对方表在中间表外键列的名字

@Fetch(FetchMode.SELECT)select、join、subselect和xml一致。
@BatchSize(size = 20)和xml一致,可以写在set属性上,也可以写在本类class类名上。
@Cascade({CascadeType.DELETE,CascadeType.SAVE_UPDATE}) 由于hibernate对jpa的cascade支持不好,尽量采用这种写法。

一对多双向关联范例:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = “userid”)
@Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
private User user;
<many-to-one name=“user” class=“domain.User” column=“userid” cascade=“save-update”/>

@OneToMany(mappedBy = "user")
@Cascade({CascadeType.DELETE,CascadeType.SAVE_UPDATE})
private Set&lt;Account&gt; accounts =new HashSet&lt;Account&gt;();
    &lt;set name="accounts" cascade="save-update,delete" inverse="true"&gt;
        &lt;key column="userid"&gt;&lt;/key&gt;
        &lt;one-to-many class="domain.Account"/&gt;
    &lt;/set&gt;

多对多双向关联范例:
@ManyToMany()
@JoinTable(name=“user_role”,joinColumns = @JoinColumn(name = “uid”),inverseJoinColumns = @JoinColumn(name = “rid”))
@Cascade({CascadeType.SAVE_UPDATE})
private Set<Role> roles=new HashSet<Role>();
<set name=“roles” table=“user_role” cascade=“save-update”>
<key column=“uid”/>
<many-to-many class=“domain.Role” column=“rid”/>
</set>

@ManyToMany(mappedBy = "roles")
@Cascade({CascadeType.SAVE_UPDATE})
private Set&lt;User&gt; users=new HashSet&lt;User&gt;();

    &lt;set name="users" table="user_role" inverse="true"&gt;
        &lt;key column="rid"&gt;&lt;/key&gt;
        &lt;many-to-many class="domain.User" column="uid"/&gt;
    &lt;/set&gt;

【【ssh整合要点】】
spring整合struts2
1、web中配置spring的监听器,读取spring的配置文件,启动ioc容器。
<!–配置Spring监听器–>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListene</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
2、action(注意所有action都是多例的),需要交给spring去创建,才能进行service的注入。
<bean id=“login_action” class=“Actions.LoginAction” scope=“prototype”/> 注意是多例的
<package name=“myPackage” extends=“struts-default”>
<action name=“login” class=“login_action”> //这里填写的是bean的id。
<result name=“success”>/welcom.jsp</result>
<result name=“error”>/error.jsp</result>
</action>
</package>
这样写还不行,还需要引入能够去ioc查找的插件
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.3.15.1</version>
</dependency>

spring整合hibernate:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
1、<!–配置session工厂,注意id,只能叫这名字–>
<bean id=“sessionFactory” class=“org.springframework.orm.hibernate4.LocalSessionFactoryBean”>
<property name=“hibernateProperties”>
<prop key=“hibernate.dialect”>org.hibernate.dialect.MySQLDialect</prop>
<prop key=“hibernate.show_sql”>true</prop>
<prop key=“hibernate.format_sql”>true</prop>
<prop key=“hibernate.hbm2ddl.auto”>update</prop>

&lt;/property&gt;
&lt;mappingResources&gt;
	&lt;list&gt;
		&lt;value&gt;...xml&lt;/value&gt;
	&lt;/list&gt;
&lt;/mappingResources&gt;
&lt;!-- 可选配置也由spring管理,以下可以选择引入一个hibernate的配置文件--&gt;
&lt;property name="configLocations" value="classpath:hibernate.cfg.xml"/&gt;
	&lt;property name="dataSource" ref="dataSource"/&gt;//连接池自己创建,使用c3p0或者dhcp都可以

</bean>
2、写dao实现类,继承HibernateDaoSupport,重写父类的setMySessionFactory方法,注入sessionFactory。
@Autowired
public void setMySessionFactory(SessionFactory sessionFactory){
super.setSessionFactory(sessionFactory);
}

解决jsp懒加载no-session问题:
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>flushMode</param-name>
<param-value>AUTO</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

【hibernatetemplate 常用api】
1:get/load存取单条数据
2:save/update/saveOrUpdate/delete 保存/更新/删除操作
3:查询操作:
find(String queryString, Object[] values);hql查询的封装形式
findByExample(Object exampleEntity, int firstResult, int maxResults) 可以根据一个vo对象进行查询,带分页。拼接条件不支持:主键、外键、null,且拼接条件只支持=或 like 其他的>、< 、in 之类的不支持,有一定的限制
findByNamedParam(String queryString , String[] paramName , Object[] value) 参数名和参数值都通过方法指定,占位符为:参数名的形式。
findByValueBean(String queryString , Object value);
String queryString= “from bean.User u where u.name=:myName and u.password=:myPassword”;

this.getHibernateTemplate().findByValueBean(queryString , valueBean);bean中必须至少有该二属性,并提供
set方法。
getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults)离线条件查询的分页形式。
criteria=DetachedCriteria.forClass(Paper.class);
criteria.add(Restrictions.in(“TExams”, examsList)).add(Restrictions.eq(“patype”, 0));

【【jpa】】
jpa是sun的orm规范,操作api全都是抽象类和接口,hibernate等框架对这套规范进行了实现。今天学习的就是基于hibernate的jpa。
maven:
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.4.10.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>5.4.10.Final</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
</dependencies>

1、配置文件resources/META-INF/persistence.xml
<?xml version=“1.0” encoding=“UTF-8”?>
<persistence xmlns=“http://java.sun.com/xml/ns/persistence” version=“2.0”>
<!–unit为持久化单元节点:
name:单元名称
type:事务管理方式
JTA:分布式事务管理
RESOURCE_LOCAL 单表本地事务管理
–>
<persistence-unit name=“myJpa” transaction-type=“RESOURCE_LOCAL”>
<!–jpa的实现方式–>
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!–数据源信息–>
<properties>
<property name=“javax.persistence.jdbc.driver” value=“com.mysql.cj.jdbc.Driver”/>
<property name=“javax.persistence.jdbc.url” value=“jdbc:mysql://localhost:3306/test”/>
<property name=“javax.persistence.jdbc.user” value=“root”/>
<property name=“javax.persistence.jdbc.password” value=“JIANGkui1”/>
<!–可选配置,配置jpa实现方的配置信息,也即hibernate的可选配置–>
<property name=“hibernate.show_sql” value=“true”/>
<property name=“hibernate.format_sql” value=“true”/>
<property name=“hibernate.hbm2ddl.auto” value=“validate”/>
</properties>
</persistence-unit>
</persistence>

2、使用api
public class Jpatest {

static EntityManager manager;
static EntityTransaction transaction;
static EntityManagerFactory factory;

@BeforeClass
public static void  init(){

// Configuration configuration=new Configuration().configure();
// SessionFactory sessionFactory = configuration.buildSessionFactory();
// session = sessionFactory.getCurrentSession();
// transaction = session.beginTransaction();
factory = Persistence.createEntityManagerFactory(“myJpa”);
manager = factory.createEntityManager();
transaction = manager.getTransaction();
transaction.begin();
}
@AfterClass
public static void close(){
// transaction.commit();
session.close();
transaction.commit();
manager.close();
factory.close();
}
@Test
public void testsave(){
Account account = new Account();
account.setMoney(2001f);
account.setName(“mybatis-annotasion”);
User user = new User();
user.setUserName(“天皇号”);
user.getAccounts().add(account);
account.setUser(user);
// session.save(user);
manager.persist(account);
}
}
EntityManager对象基本删增改查:
presist、merge、remove、find/getRefrence
和hibernate:save/update/delete/get/find基本一一对应。
jpql查询:
和hibernate的hql一摸一样,包括聚合函数、fetch多表连接等,都是一样的写法:
List<User> resultList = manager.createQuery(“from User where userName like ?1”).setParameter(1, “杨%”).getResultList();
qbc查询,和新版qbcui一样:
CriteriaBuilder criteriaBuilder = manager.getCriteriaBuilder();
CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);

【【spring data jpa】】
spring对jpa规范的代码进行了封装,相当于hibernateTemplate和hibernate原生api的关系。
<?xml version=“1.0” encoding=“UTF-8”?>
<project xmlns=“http://maven.apache.org/POM/4.0.0”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>
<modelVersion>4.0.0</modelVersion>

&lt;groupId&gt;htyy&lt;/groupId&gt;
&lt;artifactId&gt;springdatajpademo&lt;/artifactId&gt;
&lt;version&gt;1&lt;/version&gt;
&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;junit&lt;/groupId&gt;
        &lt;artifactId&gt;junit&lt;/artifactId&gt;
        &lt;version&gt;4.12&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;!--数据库--&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;mysql&lt;/groupId&gt;
        &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
        &lt;version&gt;8.0.13&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;c3p0&lt;/groupId&gt;
        &lt;artifactId&gt;c3p0&lt;/artifactId&gt;
        &lt;version&gt;0.9.1.2&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;!--SPRING--&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework&lt;/groupId&gt;
        &lt;artifactId&gt;spring-context&lt;/artifactId&gt;
        &lt;version&gt;5.0.2.RELEASE&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework&lt;/groupId&gt;
        &lt;artifactId&gt;spring-context-support&lt;/artifactId&gt;
        &lt;version&gt;5.0.2.RELEASE&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework&lt;/groupId&gt;
        &lt;artifactId&gt;spring-test&lt;/artifactId&gt;
        &lt;version&gt;5.0.2.RELEASE&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework&lt;/groupId&gt;
        &lt;artifactId&gt;spring-jdbc&lt;/artifactId&gt;
        &lt;version&gt;5.0.2.RELEASE&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework&lt;/groupId&gt;
        &lt;artifactId&gt;spring-tx&lt;/artifactId&gt;
        &lt;version&gt;5.0.2.RELEASE&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework&lt;/groupId&gt;
        &lt;artifactId&gt;spring-orm&lt;/artifactId&gt;
        &lt;version&gt;5.0.2.RELEASE&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework&lt;/groupId&gt;
        &lt;artifactId&gt;spring-aop&lt;/artifactId&gt;
        &lt;version&gt;5.0.2.RELEASE&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.aspectj&lt;/groupId&gt;
        &lt;artifactId&gt;aspectjweaver&lt;/artifactId&gt;
        &lt;version&gt;1.8.7&lt;/version&gt;
    &lt;/dependency&gt;

    &lt;!--hibernate--&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.hibernate&lt;/groupId&gt;
        &lt;artifactId&gt;hibernate-core&lt;/artifactId&gt;
        &lt;version&gt;5.4.10.Final&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.hibernate&lt;/groupId&gt;
        &lt;artifactId&gt;hibernate-entitymanager&lt;/artifactId&gt;
        &lt;version&gt;5.4.10.Final&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.hibernate&lt;/groupId&gt;
        &lt;artifactId&gt;hibernate-validator&lt;/artifactId&gt;
        &lt;version&gt;5.4.1.Final&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;!--springdata jpa--&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.data&lt;/groupId&gt;
        &lt;artifactId&gt;spring-data-jpa&lt;/artifactId&gt;
        &lt;version&gt;2.1.10.RELEASE&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;javax.el&lt;/groupId&gt;
        &lt;artifactId&gt;javax.el-api&lt;/artifactId&gt;
        &lt;version&gt;3.0.0&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.glassfish.web&lt;/groupId&gt;
        &lt;artifactId&gt;javax.el&lt;/artifactId&gt;
        &lt;version&gt;2.2.6&lt;/version&gt;
    &lt;/dependency&gt;

    &lt;!--log--&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;log4j&lt;/groupId&gt;
        &lt;artifactId&gt;log4j&lt;/artifactId&gt;
        &lt;version&gt;1.2.17&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
        &lt;artifactId&gt;slf4j-api&lt;/artifactId&gt;
        &lt;version&gt;1.7.5&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
        &lt;artifactId&gt;slf4j-log4j12&lt;/artifactId&gt;
        &lt;version&gt;1.7.5&lt;/version&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;

</project>

2、使用spirng配置dao的所有配置,包括jpa的配置
<?xml version=“1.0” encoding=“UTF-8”?>
<beans xmlns=“http://www.springframework.org/schema/beans”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xmlns:context=“http://www.springframework.org/schema/context”
xmlns:aop=“http://www.springframework.org/schema/aop”
xmlns:tx=“http://www.springframework.org/schema/tx”
xmlns:jpa=“http://www.springframework.org/schema/data/jpa”
xmlns:task=“http://www.springframework.org/schema/task”
xmlns:jdbc=“http://www.springframework.org/schema/jdbc”
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
"
>

&lt;context:component-scan base-package="htyy"/&gt;
&lt;aop:aspectj-autoproxy&gt;&lt;/aop:aspectj-autoproxy&gt;
&lt;tx:annotation-driven&gt;&lt;/tx:annotation-driven&gt;

&lt;!--创建工厂对象,交给spring管理--&gt;
&lt;bean id="entityManagerFactoryBean" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&gt;
    &lt;property name="dataSource" ref="dataSource"/&gt;
    &lt;!--配置实体类所在包,用于扫描entity等映射注解--&gt;
    &lt;property name="packagesToScan" value="htyy.domain"/&gt;
    &lt;!--jpa实现方式--&gt;
    &lt;property name="persistenceProvider"&gt;
            &lt;bean class="org.hibernate.jpa.HibernatePersistenceProvider"/&gt;
    &lt;/property&gt;
    &lt;!--配置hibernate的一些可选配置--&gt;
    &lt;property name="jpaVendorAdapter"&gt;
        &lt;bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"&gt;
            &lt;property name="generateDdl" value="false"/&gt;
            &lt;property name="database" value="MYSQL"/&gt;
            &lt;property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/&gt;
            &lt;property name="showSql" value="true"/&gt;

        &lt;/bean&gt;
    &lt;/property&gt;
    &lt;!--jpa的方言,即高级特性--&gt;
    &lt;property name="jpaDialect"&gt;
        &lt;bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/&gt;
    &lt;/property&gt;
  &lt;!--配置hibernate自己的属性--&gt;
    &lt;property name="jpaProperties"&gt;
        &lt;props&gt;
            &lt;prop key="hibernate.hbm2ddl.auto"&gt;validate&lt;/prop&gt;
        &lt;/props&gt;
    &lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"&gt;
    &lt;property name="driverClass" value="com.mysql.cj.jdbc.Driver"&gt;&lt;/property&gt;
    &lt;property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"&gt;&lt;/property&gt;
    &lt;property name="user" value="root"&gt;&lt;/property&gt;
    &lt;property name="password" value="JIANGkui1"&gt;&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" &gt;
    &lt;property name="entityManagerFactory" ref="entityManagerFactoryBean"/&gt;
&lt;/bean&gt;
&lt;!--spring整合datajpa,也即自动扫描dao接口,创建实现类--&gt;
&lt;jpa:repositories base-package="htyy.dao" transaction-manager-ref="transactionManager"
                  entity-manager-factory-ref="entityManagerFactoryBean"/&gt;

</beans>

3、编写dao接口,继承jpa的含有默认方法的接口类。
/**

  • JpaRepository<Account,Integer> 封装了基本crud操作,泛型为要操作的实体对象和该实体对象的主键类型
  • JpaSpecificationExecutor<Account> 封装了复杂查询(分页等)
    */
    @Repository
    public interface IAccountDao extends JpaRepository<Account,Integer>, JpaSpecificationExecutor<Account> {
    }

此时自己编写的iaccountdao已经具有所有方法,如:
accountDao.findById(3); 返回一个代理对象,可以通过get或者orelse得到account对象,建议后者。
accountDao.findById(24).orElse(null);标准的orelse方法得到实体类
accountDao.getOne(1); lazy查询的方法,延迟加载的方式得到代理对象。
accountDao.deleteById(2);accountDao.delete(account);删除,可以根据id,或者删除查询到的实体。
accountDao.findAll();查询所有。
accountDao.save(account) 保存或更新都是调用的这个方法,有id更新,无id保存。
accountDao.count() 返回一个long类型的总数量。
accountDao.existsById(4) 返回一个boolean,判断是否存在该id的值。

【hql查询(jpaql查询)】
使用@Query注解在接口方法名上写hql语句即可:
@Query(“from Account where name like ?1”)
public List<Account> findByname(String name);

也可以使用@Modifying+@Query表示要写update语句
@Query(“update Account set name = ?1”)
@Modifying
public List<Account> findByname(String name);
罪恶,query注解有一个nativeQuery参数,默认为false,true代表使用sql查询,查询的结果不能自动封装,只能使用list<object[]>进行接收。

参数解析的方式有如下几种:
1、按位置获取?1 ?2
2、按名称获取:name :money,此时需要使用@param注解在方法中进行名称匹配:
@Param(“name”) String name,@Param(“money”) String money
3、类似mybatis,使用#{#表达式}
@Query(“from Account where name like :#{#account.name} and money >= :#{#account.money}”)
public List<Account> findByExample(@Param(“account”) Account account);

【方法名称规则查询】
如果按照springdatajpa固定的方法规则,那么会自动給该方法进行代理实现。
1、findBy+规范属性名(属性名称首字母大写),即可完成一个from entity where fieldname=?的查询。
public List<Account> findByName(String name);
2、findBy+规范属性名+查询方式(Like/isnull),可以指定查询方式是=,like,isnull。
3、多参数情况下,findBY+(属性名查询)+And/Or+(属性名查询)即可,排序等也可以写在后面:
findByNameLikeAndMoneyAfterOrderByMoney

【复杂条件查询】
Optional<T> findOne(@Nullable Specification<T> var1); 查询一个
List<T> findAll(@Nullable Specification<T> var1);查询多个
Page<T> findAll(@Nullable Specification<T> var1, Pageable var2);带分页,返回pageinfo对象
List<T> findAll(@Nullable Specification<T> var1, Sort var2);可排序
long count(@Nullable Specification<T> var1);返回count的数量
Specification<T>是一个接口,使用时应该使用内部类或lambd表达式自定义自己的实现类。
Predicate toPredicate(Root<T> var1, CriteriaQuery<?> var2, CriteriaBuilder var3);实现该方法。
可以发现,实际上该接口就是对cb、cq、root这三个qbc查询的封装,编写好规则后,使用时会默认传入。最终,只需要返回cb对象合成的一个predicate条件即可。
List<Account> all = accountDao.findAll((Specification<Account>) (root, query, cb) ->
cb.and(cb.like(root.get(“name”), “杨%”),cb.gt(root.get(“money”),3000f)));

sort是一个排序类:
Sort orders = new Sort(Sort.Direction.DESC, “money”, “id”);
Sort orders1 = orders.and(new Sort(Sort.Direction.ASC, “name”));

pageable是一个接口,我们需要使用它的实现类pagerequest:
PageRequest pageRequest = PageRequest.of(page:2, size:1, sort:orders1);
三个参数分别是当前页(从0开始),每页数量,排序条件。

Page<T>可用方法、属性如下:
getTotalElements() 当前总项目数
getTotalpages 当前总页数
getSize 得到当前设置的每页容量
getnumber 得到当前页,从0开始
getContent 得到内置的list

【多表关联】
注解关联发和在hibernate一节已经讲述,此处略过

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值