目录
2.1.EJB中的有状态与无状态( @stateless/@stateful )
2.2.@Stateless 与 @ApplicationScoped
2.5.javax.ws.rs.Path @path 标注的类 是单例模式吗
2.6.EJB标签中的@ApplicationScoped和@Stateless区别
・1.1.1.配置文件 --- persistence.xml --- 中指定数据源
■1.4. jpa 框架在实体类(Entity)中添加非数据库字段的属性---@Transient
■1.10.JTA 与 RESOURCE_LOCAL 之间的区别
■1.12.关于【persistence.xml】 中的【transaction-type】
■1.13. 关于【persistence.xml】 中的【shared-cache-mode】
■1.16.WebSphere中,对于 JAP的实现,每次查询之后,还要根据主键,再查询一次(坑!!!)
■1.17.ibm websphere PersistenceProviderImpl 指定 默认 Schema
■1.18.查看WebSphere的持久化(persistence)设定。
・websphere 一个Cluster配置了多个node,实现了负载平衡,但是如何访问这个Cluster对应的虚拟主机的IP地址
・在Web服务器中配置WebSphere中的Cluster需要完成以下步骤:
・查看Cell,Node,Server的构造--- 【树形结构】
( ↑ ★ EJB中的各个方法,都是一个事务,中间处理出错,可以回滚 ★)
・查看所有的Application部署的位置(Context root) 上下文
・查看Server,Node,Cluster的构造--- 【一览表】
・查看Server上面部署的App的资源情报(比如 JNDI)
・查看Server的访问限制(比如Post请求的最大size)
5.1. Failed to load webapp: Context root /xxx/***
5.2.openjpa-2.2.3-SNAPSHOT-r422266:1764177 nonfatal store error
└org.apache.openjpa.persistence.EntityNotFoundException
5.3.org.apache.openjpa.lib.jdbc.ReportingSQLException
・配置2:【WebSphere中 查看数据源使用的数据库用户】
・Ear读取的xxxx.properties文件目录指定 (設定)
・Ear读取的xxxx.properties文件目录指定 (指定)
11.1.在 WebSphere中 rollout是什么意思
2.查询不到数据---返回值不是List 是一个单独的Bean
14.查询核心【javax.persistence.EntityManager】
=====
1.前言
看了一段业务对于的处理代码,
代码里面没有任何事务处理的相关处理,
却实现了事务功能。
■实现原理:容器管理事务
容器管理事务主要是通过容器自动控制事务的开启,提交和回滚,开发人员不需要手工编写代码,由容器来控制事务的边界,一般来说是业务方法的开始
■代码实现简单描述:
・ 代码部署在WebSphere上
・数据库处理在Service层中,在Sevice层中,有多个对数据库的操作。
・是使用JPA (ORM)实现数据库操作的。可以实现回滚功能。
・有关于JPA的配置文件 WEB-INF/classes/META-INF/persistence.xml
・JPA的配置文件中,管理事务管理方式是JTA,即是由应用程序服务器的实现事务管理。
・ service层中,使用了一个EJB的标签:@Stateless。
2.EJB 标签
【StateLess】基本概念
import javax.ejb.Stateless;
基本概念:
有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。
无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象.不能保存数据,是不变类,是线程安全的。
代码更好理解:
2.1.EJB中的有状态与无状态( @stateless/@stateful )
1.Stateful session bean的每个用户都有自己的一个实例,所以两者对stateful session bean的操作不会影响对方。另外注意:如果后面需要操作某个用户的实例,你必须在客户端缓存Bean的Stub对象(JSP通常的做法是用Session缓存),这样在后面每次调用中,容器才知道要提供相同的bean实例。
2.Stateless Session Bean不负责记录使用者状态,Stateless Session Bean一旦实例化就被加进会话池中,各个用户都可以共用。如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响。
3.从内存方面来看,Stateful Session Bean与Stateless Session Bean比较,Stateful Session Bean会消耗J2EE Server 较多的内存,然而Stateful Session Bean的优势却在于他可以维持使用者的状态。
2.2.@Stateless 与 @ApplicationScoped
・@Stateless标注的类,会被作为EJB,在WebSphere的EJB管理中被看到
・@Stateless标注的类,因为是EJB,每一个方法,都有事务。(整个方法的开始,结束,作为一个事务被管理)
・被@Stateless 或 @ApplicationScoped 标注的类,都是被EJB容器管理的,可以在别的类中,使用@inject类,注入进来
===
2.3.EJB 标签 @Stateless 介绍
@Stateless是Java Enterprise Edition (Java EE)中的一种注解标签,用于表示一个无状态的会话Bean (Session Bean)。
无状态的会话Bean是一种轻量级的组件,它不保留任何客户端请求的状态信息。与有状态的会话Bean相比,无状态会话Bean更具可伸缩性和性能优势,适合处理多个并发请求。
@Stateless标签用于标识一个Java类,将其声明为无状态会话Bean。它可以应用在类级别或接口级别。
使用@Stateless标签,可以享受到以下好处:
- 无状态:无状态会话Bean不保留客户端请求的状态信息,使其更容易在多线程环境下工作。
- 轻量级:无状态会话Bean是轻量级的,创建和销毁开销较小。
- 可伸缩性:由于无状态,可以并发处理多个客户端请求,提高系统的可伸缩性。
- 事务管理:可以通过使用注解或配置文件来管理会话Bean的事务,确保数据的一致性。
- 易于测试:无状态会话Bean易于单元测试和集成测试,无需考虑状态的维护和交互。
使用@Stateless标签声明的无状态会话Bean可以通过依赖注入 (Dependency Injection) 在其他组件中使用。它们通常用于实现业务逻辑和处理事务,例如处理用户认证、访问数据库或调用其他远程服务。
总的来说,@Stateless标签是Java EE中用于标识无状态会话Bean的注解,它提供了一种轻量级、可伸缩和无状态的方式来处理并发请求和业务逻辑。
xx
2.4.@Stateless 标注的类,是单例模式吗
・是的,使用@Stateless注解标注的类可以看作是单例模式的实现。
・在Java EE中,每次客户端请求到达时,容器都会为该请求创建一个新的实例对象。但是,由于@Stateless会话Bean是无状态的,它们不会保存任何客户端请求的状态信息。因此,容器可以缓存和重用这些实例对象,使它们看起来像是单例对象。
・每个无状态会话Bean实例对象可以由多个并发请求共享,容器可以根据需求创建更多的实例对象来处理请求。这种池化机制可以提高性能和可伸缩性。
・需要注意的是,由于无状态会话Bean的实例对象是共享的,因此应该避免在无状态会话Bean的属性中存储任何与请求相关的状态信息。
・总结来说,@Stateless标注的类在Java EE中可以被视为单例模式的实现,但是与传统的单例模式不同,它们是无状态的会话Bean,可以由多个并发请求共享。
===
・尽管每个请求都会创建一个新的实例,但由于@Stateless会话Bean是无状态的,它们之间的实例之间是相互独立的,不会交互或共享状态。因此,在整个应用程序的生命周期内,容器可以重用和缓存这些@Stateless会话Bean实例,以提高性能和效率。这种重用和缓存的方式使@Stateless会话Bean看起来像是单例对象。
・需要注意的是,@Stateless注解并不是用来实现单例模式的,而是定义了一种被容器管理的无状态会话组件。如果需要实现单例模式,可以使用其他的手段,比如使用@Singleton注解来标记一个类或组件为单例,并通过容器管理其生命周期。
xx
2.5.javax.ws.rs.Path @path 标注的类 是单例模式吗
・被@javax.ws.rs.Path标注的类在JAX-RS中不是单例模式。
・在JAX-RS中,每个请求都会创建一个新的实例对象来处理该请求。这意味着每个带有@Path注解的类都会有多个实例对象,每个对象负责处理不同的请求。
・这种方式的好处是每个请求都有自己的上下文和状态,不会相互干扰。每个实例对象可以临时保存和处理请求相关的数据。
・因此,与使用@Stateless注解的类不同,使用@Path注解的类不是单例模式,而是每次请求创建一个新的实例。这使得JAX-RS更灵活和可伸缩,适用于处理每个请求的情况。
xx
2.6.EJB标签中的@ApplicationScoped和@Stateless区别
EJB标签中的@ApplicationScoped和@Stateless是用于不同的情况和目的,它们之间有以下区别:
作用范围(Scope):
- @ApplicationScoped:该注解用于标记一个EJB组件或Bean,表示它的生命周期与应用程序的生命周期相同。这意味着在整个应用程序中只会创建一个实例,该实例将在应用程序启动时创建,并在整个应用程序的生命周期内被共享和复用。
- @Stateless:该注解用于标记一个无状态的EJB组件或Bean,表示每个请求将使用一个新的实例来处理。这意味着每个请求都将独立地创建一个新的实例,并在该请求处理完成后被销毁。Stateless代表无状态的,因为实例之间不会共享任何状态信息。
生命周期管理:
- @ApplicationScoped:标注的组件的生命周期由容器管理,容器会在应用程序启动时创建一个实例,并在应用程序关闭时销毁该实例。可以通过@PostConstruct和@PreDestroy注解来标注初始化和销毁方法。
- @Stateless:标注的组件的生命周期也由容器管理,但是每个请求都会创建一个新的实例,并在请求处理完成后销毁。因此,无需手动管理其生命周期。
状态(State):
- @ApplicationScoped:由于该注解表示一个应用程序级别的组件,它可以在各个类和方法之间共享状态信息。因此,在同一个应用程序的不同部分访问相同的@ApplicationScoped组件时,可以共享相同的状态。
- @Stateless:由于该注解表示无状态的组件,实例之间不会共享任何状态信息。每个请求都将获得一个独立的实例,该实例仅在请求处理期间可用,并在请求完成后被销毁。
总的来说,@ApplicationScoped适用于需要共享状态信息的一些组件,例如全局数据或缓存组件。而@Stateless适用于需要为每个请求提供独立的实例和状态的组件,例如处理业务逻辑的服务组件。
xx
2.7.@ApplicationScoped 是单例模式吗
是的,@ApplicationScoped可以用来实现单例模式。当一个类或组件被标记为@ApplicationScoped时,容器会在应用程序启动时创建一个实例,并在整个应用程序的生命周期内共享和复用该实例。
每个应用程序只会有一个@ApplicationScoped标注的实例,因此可以将其视为一个全局的单例对象。无论是在同一个类内部还是在整个应用程序中的不同部分,都可以使用@Inject或@EJB注解来获取对该单例实例的引用。
需要注意的是,@ApplicationScoped并不是Java EE中的原生注解,而是来自于CDI(Contexts and Dependency Injection)规范。它通常与Servlet、JSF(JavaServer Faces)或其他支持CDI的框架一起使用。
xx
2.JPA
■定义
JPA(Java Persistence API)和JDBC类似,也是官方定义的一组接口,但是它相比传统的JDBC,它是为了实现ORM而生的,即Object-Relationl Mapping,它的作用是在关系型数据库和对象之间形成一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了。
=========================================================
■1.1.配置文件 --- persistence.xml
persistence.xml // JPA persistence.xml
JPA persistence.xml 文件初学者指南_allway2的博客-CSDN博客_persistence.xml
persistence.xml在下面这个目录中
WEB-INF/classes/META-INF
・1.1.1.配置文件 --- persistence.xml --- 中指定数据源
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<!-- 有一个或者多个persistence-unit -->
<!-- transaction-type:在J2EE应用服务器中缺省为JTA(Java Transaction API),在J2SE和简单的servlet容器中缺省为标准本地事务 RESOURCE_LOCAL。为避免歧义,我们应明确设置 -->
<!-- persistence-unit里面可以为空,但是如果设置,必须要顺序 -->
<persistence-unit name="EntityMappingsTest" transaction-type="RESOURCE_LOCAL">
<!-- 首先是<description>,小例子不提供 -->
<!-- provider:具体的javax.persistence.spi.PersistenceProvider实现,缺省值为classpath中第一个JPA的实现 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!-- 如果persistence-unit的transaction-type为JTA,使用<jta-data-source>,如果为RESOURCE_LOCAL,使用<non-jta-data-source>。他们的区别在于后者使用EntityTransaction接口,而前者使用UserTransaction接口,缺省是前者(JTA)。它们均采用JNDI(Java Naming and Directory Interface)方式,给出数据源。 -->
<non-jta-data-source>java:comp/env/jdbc/learnTest</non-jta-data-source>
<!-- <mapping-file>:基于classpath的XML mapping file,如果不指定,缺省为orm.xml,可以设置多个mapping-file -->
<!-- <jar-file>:JPA实现将对jar包进行绑定标记扫描,如果里面有@Entity,@Embeddable,@javax.persistence.MappedSuperclass或者@javax.persistence.Converter,加入本持续化单元中,可以设置多个jar-file -->
<!-- <class>:JPA实现将对这个class加入到持续化单元中,这个class必须带有@Entity,@Embeddable,@javax.persistence.MappedSuperclass或者@javax.persistence.Converter。可以设置多个class -->
<!-- 设置<exclude-unlisted-classes/>或者<exclude-unlisted-classes>true</exclude-unlisted-classes>表示只关注在jar-file和在class中所设置的,不扫描其他。删除<exclude-unlisted-classes/>或者<exclude-unlisted-classes>false</exclude-unlisted-classes>则表示将扫描classpath位置;如果本文件在JAR文件,则扫描JAR文件的classes,如果本文件位于classes中的某个特定目录,则只扫描该目录下的文件(例如指定到某个package)。 -->
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<!-- <shared-cache-mode>:是否缓存entity,-->
<!-- ➤ NONE表示不缓存,-->
<!-- ➤ ALL表示缓存所有的entities。-->
<!-- ➤ ENABLE_SELECTIVE 表示只缓存带有@Cacheable或者@Cacheable(true)标识的entity -->
<!-- ➤ DISABLE_SELECTIVE 表示除了@Cacheable(false)外均缓存 -->
<!-- ➤ UNSPECIFIED 表示有JPA的提供者来决定,Hibernate ORM缺省为ENABLE_SELECTIVE,但采用这种方式,对于移植可能会存在混淆,应明确设定 -->
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<!-- <validation-mode> -->
<!-- ➤ NONE表示不使用Bean validator,-->
<!-- ➤ CALLBACK表示在写操作(insert,update,delete)前进行validate -->
<!-- ➤ AUTO,如果classpath中存在Bean validator provider,则CALLBACK,不存在则NONE -->
<!-- 如果使用validate,而我们自定义了spring framework的validator,JPA将忽略这个自定义。因此建议使用NONE,在数据持久化之前进行校验,而不是在持久化这个层面。 -->
<validation-mode>NONE</validation-mode>
<!-- <properties>以name-value的方式提供其他JPA属性(如JDBC连接,用户,密码,schema产生成设置等)以及提供者特有的属性(如Hibernate设置)。 -->
<properties>
<!-- 禁止schema生成,即不根据entity创建表格 -->
<property name="javax.persistence.schema-generation.database.action" value="none" />
</properties>
</persistence-unit>
</persistence>
=========
JNDI
java:comp/env 是环境命名上下文(environment naming context(ENC)),是在EJB规范1.1以后引入的,引入这个是为了解决原来JNDI查找所引起的冲突问题,也是为了提高EJB或者J2EE应用的移植性。
java:comp/env/jdbc/
java:comp/env/jdbc/YourDataSourceName
https://www.cnblogs.com/dekn/archive/2006/02/14/330308.html
=========
■1.2.OSS jar
org.eclipse.persistence.jpa
java - 我对Maven依赖感到困惑:“org.eclipse.persistence.jpa”和“org.hibernate” | persistence
■1.3.一些JPA的类(举例)
javax.persistence.PersistenceContext
(所属jar javax.persistence-2.x.x.jar )
■1.4. jpa 框架在实体类(Entity)中添加非数据库字段的属性---@Transient
问:jpa表实体的字段和表的字段是一一对应的。比如,那么,如果我在查询时,想在表字段的基础上添加几个返回的字段,怎么办?
解:在实体类中添加我们想添加的字段,并加上注解:@Transient,
@Transient
privite String userId;
效果:这样在调用此类返回时,便有了此字段,我们可以给这个字段赋值,进行操作,而且不会在数据库中添加这个字段。
■1.5. JPA 原生配置
■1.6. EntityManager 管理事务
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
public class EMUtil {
public static EntityManager getEM() {
return Persistence.createEntityManagerFactory("hotel").createEntityManager();
}
}
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import javax.persistence.Query;
----
public void insertMember(Member member) {
em.getTransaction().begin();
em.persist(member);
em.getTransaction().commit();
// 仅仅一个数据库连接,就不关了
// em.close();
}
----
import javax.persistence.*;
@Entity
@Table(name = "member")
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String phone;
private String identity;
private String username;
private String password;
/** getter and setter **/
}
----
■1.7.ORM框架
JPA(Java Persistence API), JPA是一个ORM的标准规范,而不是一个具体的ORM框架
( ORM(object relation mapping) 对象关系映射关系 ,面向对象的对象模型和关系型数据之间的相互转换。)
・Hibernate: Hibernate是一个全自动的ORM模型,Hibernate可以自动生成SQL语句,自动执行。
・MyBatis:MyBatis是一款半自动的ORM模型,它支持定制化 SQL、存储过程及高级映射。
・【javax.persistence-2.x.x.jar】或【javaee-web-api-7.0.jar】中的接口,类
javax.persistence.Query和javax.persistence.EntityManager都是JAP发布的接口,是用于对象持久化API。
使用,[em.createNativeQuery(sql);]创建Query
■1.8.javax.persistence
javax.persistence.Persistence - JPA class
■1.9.JPA 中的 JTA 是什么:
JPA 中的 JTA 是 Java Transaction API 的缩写,它是一种 Java 的事务管理规范。JTA 规范定义了一种标准的 API,允许应用程序在多个资源(例如数据库、消息队列等)之间执行分布式事务。在 JPA 中,JTA 可以用来管理实体操作的事务,确保实体操作的原子性、一致性、隔离性和持久性。JPA 实现通常会使用 JTA 作为事务管理器,以便在多个数据源之间实现分布式事务处理。
■1.9.transaction-type
JPA 事务策略,它可以采用以下两个值之一:
・JTA
・RESOURCE_LOCAL
如果您使用的是 JTA,您可以使用jta-data-source为关联的 JTA 指定 JNDI 名称DataSource,
而对于RESOURCE_LOCAL,您需要使用non-jta-data-source.
■1.10.JTA 与 RESOURCE_LOCAL 之间的区别
JPA实现可以选择自己管理事务(RESOURCE_LOCAL),还是由应用程序服务器的JTA实现对其进行管理。
在大多数情况下,RESOURCE_LOCAL可以。这将使用基本的JDBC级事务。缺点是该事务对于JPA持久性单元而言是本地的,因此,如果您想要一个跨多个持久性单元(或其他数据库)的事务,则RESOURCE_LOCAL可能不够好。
JTA还用于跨JMS和JCA之类的系统管理事务,但这对我们大多数人来说是相当奇特的用法。
要使用JTA,您需要在应用程序服务器中对其进行支持,并且还需要JDBC驱动程序的支持
■1.11.JPA原生代码
【JAVA】-【JPA】-orm思想及jpa配置_刘晓伟-liu的博客-CSDN博客
■1.12.关于【persistence.xml】 中的【transaction-type】
默认值
(属性)使用的事务类型。
有两种:JTA和RESOURCE_LOCAL(在J2EE环境中默认是【JTA】,而在J2SE环境中默认是【RESOURCE_LOCAL】)。
当使用的是jta数据源时,默认的事务类型是JTA,如果使用的不是jta数据源时,默认的事务类型就是RESOURCE_LOCAL。
内容说明
比较RESOURCE_LOCAL和JTA持久性上下文
==========
使用<persistence-unit transaction-type =“RESOURCE_LOCAL”> 您负责EntityManager(PersistenceContext / Cache)创建和跟踪...-----
您必须使用EntityManagerFactory来获取EntityManager
生成的EntityManager实例是 PersistenceContext / Cache
EntityManagerFactory只能通过@PersistenceUnit注释注入(不是@PersistenceContext)
不允许使用@PersistenceContext来引用RESOURCE_LOCAL类型的单元
您必须使用EntityTransaction API开始/提交对EntityManger的每次调用
两次调用entityManagerFactory.createEntityManager()会导致两个独立的EntityManager实例,从而产生两个独立的PersistenceContexts / Caches。
使用多个EntityManager 实例 几乎绝不是一个好主意(除非你已经破坏了第一个实体 ,否则不要创建第二个实例 )==============
使用<persistence-unit transaction-type =“JTA”> CONTAINER将执行EntityManager(PersistenceContext / Cache)创建和跟踪...-----
您不能使用EntityManagerFactory来获取EntityManager
您只能获取容器提供的EntityManager
可以通过@PersistenceContext注释注入EntityManager (不是@PersistenceUnit)
您不能使用@PersistenceUnit来引用JTA类型的单位
容器给出的EntityManager是对与JTA事务关联的PersistenceContext / Cache的引用 。
如果没有正在进行的JTA事务, 则无法使用 EntityManager,因为没有PersistenceContext / Cache。
具有EntityManager引用到同一事务中 相同单元的每个人都将自动引用相同的PersistenceContext / Cache
在JTA 提交时刷新并清除PersistenceContext / Cache
自己负责创建 EntityManager
======================================
package com.dmsd.test;
import com.dmsd.jpa.Customer;
import org.junit.jupiter.api.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class jpaTest1 {
/**
* 测试jpa保存
* jpa操作步骤
* 1、加载配置文件创建工程对象
* 2、通过实体管理类工程获取实体管理器
* 3、开启事务
* 4、完成CRUD
* 5、提交事务-回滚事务
* 6、释放资源
*/
@Test
public void testSave(){
//加载配置文件
EntityManagerFactory factory= Persistence.createEntityManagerFactory("myjpa");//参数为配置文件中的持久化单元名称
//通过实体管理器工厂获取实体管理器
EntityManager em = factory.createEntityManager();
//获取事务对象,开启事务
EntityTransaction tx = em.getTransaction();//获取事务对象
tx.begin();//开始事务
//完成增删改查操作
Customer customer=new Customer();
customer.setCustName("test201127");
customer.setCustINdustry("beijing");
customer.setCustAddress("111");
customer.setCustLevel("1");
customer.setCustPhone("029833904");
customer.setCustSource("333");
//保存
em.persist(customer);//将实体保存到数据表中
//提交事务
tx.commit();
//释放资源
em.close();//释放实体管理器
factory.close();//释放工厂
}
}
自己负责创建时的persistence.xml文件。(要放到main下面的【src/resources】的【META-INF】目录下面)
main
└java
└resources
└META-INF
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!--
配置persistence-unit节点
称为持久化单元
name:持久化单元名称
transaction-type:事务管理的方式
JTA:分布式事务管理
RESOURCE_LOCAL:本地事务管理
-->
<persistence-unit name="myjpa" transaction-type="RESOURCE_LOCAL">
<!-- 配置jpa实现方式-->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<!-- 配置数据库信息
用户名:javax.persistence.jdbc.user
密码: javax.persistence.jdbc.password
驱动: javax.persistence.jdbc.driver
数据库地址: javax.persistence.jdbc.url
-->
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<!-- value中:mysql:///代表本地mysql数据库-3306端口。jpa代表数据库名 -->
<property name="javax.persistence.jdbc.url" value="jdbc:mysql:///jpa"/>
<!-- 可选配置,配置jpa实现方的配置信息
显示sql: false|true true为显示数据库表,false为不显示数据库表
自动创建数据库表: hibernate.hbm2ddl.auto
可选值:create:程序运行时创建数据库,如果有表先删除在创建
update:程序运行时创建表,如果有表,不会创建表
none:不会创建表
-->
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
======================================
■1.13. 关于【persistence.xml】 中的【shared-cache-mode】
https://www.cnblogs.com/zr520/p/5024127.html
■1.14.JPA介绍
https://localhost01.blog.csdn.net/article/details/83422893
===
https://www.cnblogs.com/zhuxiang1029/p/14900749.html
■1.15.JPA原生代码
【JAVA】-【JPA】-orm思想及jpa配置_刘晓伟-liu的博客-CSDN博客
■1.16.WebSphere中,对于 JAP的实现,每次查询之后,还要根据主键,再查询一次(坑!!!)
在实体类中使用了@Id注解来定义主键,那么每次查询后都会自动根据主键再查询一次。
坑:这个时候查询时,使用默认的Schema
在WebSphere中,JPA的实现通常是使用Hibernate或EclipseLink。对于JPA的实现,如果您在实体类中使用了@Id注解来定义主键,那么每次查询后都会自动根据主键再查询一次。
这是因为JPA规范中要求所有实体类必须有一个主键,而主键是唯一标识实体的属性。因此,当您进行查询操作时,JPA实现会先根据您指定的查询条件获取到符合条件的实体对象,然后再根据实体类定义的主键查询数据库获取到完整的实体对象。
这个过程是自动完成的,您无需特别关心。如果您需要优化查询性能,可以考虑使用缓存等技术来减少数据库查询次数。
====
■1.17.ibm websphere PersistenceProviderImpl 指定 默认 Schema
在 persistence.xml 文件中添加以下属性:
<properties>
<property name="javax.persistence.schema-generation.database.default-schema" value="your_schema_name"/>
</properties>
注意!!! 不同的JPA的实现, 属性的name是不同的
比如 OpenJPA 要使用下面的配置
<properties>
<property name="openjpa.jdbc.Schema" value="your_schema_name"/>
</properties>
====
■1.18.查看WebSphere的持久化(persistence)设定。
xxx
选择【サーバー】
└【サーバー・タイプ】
└【WebShpere Application Server】
└Your Server Name
==============
【コンテナー設定】
└【コンテナー・サーバー】
└ デフォルトJava Persistence API 設定 //(持久化) (JPA)
==============
===
这个版本(2.1)的是eclipse的JPA实现,
=====
2.0版本是 IBM自己的
===
xxx
■1.20.关于Open JPA
【问】
下面哪一个正确
<property name="javax.persistence.schema-generation.database.default-schemas" value="your_schema_name"/>
<property name="openjpa.jdbc.Schema" value="your_schema_name"/>
【答】
这两个属性都是用于指定数据库模式(schema)名称的,但是它们所属的持久化框架不同。
第一个属性 javax.persistence.schema-generation.database.default-schemas 属于 Java Persistence API (JPA),用于在使用 JPA 生成数据库模式时指定默认的模式名称。
第二个属性 openjpa.jdbc.Schema 属于 Apache OpenJPA,用于指定 OpenJPA 运行时使用的数据库模式名称。
因此,选择正确的属性取决于你使用的持久化框架是哪个。如果你使用的是 JPA,则应该选择第一个属性;如果你使用的是 OpenJPA,则应该选择第二个属性。
■1.21.xx
xxx
■1.22.xx
xxx
■1.23.xx
xxx
■1.24.xx
xxx
■1.25.xx
xxx
■1.26.xx
xxx
=========================================================
3.EJB-事务管理
3.1.EJB默认事务
@TransactionManagement(TransactionManagementType.CONTAINER)
表示指定事务的类型。如果省略,默认为CMT方式。
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Stateless(name = "UserManager")
@Remote
@TransactionManagement(TransactionManagementType.CONTAINER)
public class UserManagerBean implements UserManager {
@PersistenceContext
private EntityManager em ;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void addUser(String name) {
User s = new User();
s.setName(name);
em.persist(s);
System.out.println("服务器端执行成功:保存姓名" + name);
}
}
3.2.EJB的事务管理分如下两个方面
1、CMT(容器管理事务)(默认)
2、BMT(Bean管理事务)
EJB事务控制(CMT和BMT两种方式以及JTA事务) - 姜师爷闯世界 - 博客园
3.3.容器管理事务
容器管理事务主要是通过容器自动控制事务的开启,提交和回滚,开发人员不需要手工编写代码,由容器来控制事务的边界,一般来说是业务方法的开始
3.4.EJB事务【精简整理】
EJB--事务管理 . - 有梦就能实现 - 博客园 (cnblogs.com)
在EJB中有两种使用事务的方式。第一种方式(默认)通过容器管理的事务,叫CMT(Container-Managed Transaction),另一种通过Bean管理的事务叫BMT(Bean-Managed Transaction)。
如果使用容器来管理事务,那么EJB组件就不需要显式地给出begin 、commit 、abort 语句,EJB 容器会替我们考虑这些内容。EJB 容器会依据EJB组件提供者指定的事务行为来界定相应的事务边界。
在使用容器管理事务时,EJB 容器会拦截客户请求,并自动为EJB组建启动新的事务,也就是说,容器会通过begin 语句调用底层事务系统,从而启动事务。
3.5.EJB中,事务的传播
EJB的事务是容器管理的,既 CMT方式,这种情况,如何判断事务传播方式
在容器管理事务(CMT)的情况下,默认的事务传播方式通常是使用调用方的事务上下文。具体来说,如果一个 EJB 方法被调用时,调用方已经存在一个事务,那么该方法会加入该已有事务中。这相当于事务传播行为是
TransactionAttributeType.REQUIRED
,即如果有事务存在,则加入该事务;如果没有事务存在,则创建一个新事务。---
换句话说,在 CMT 中,默认的事务传播行为是以调用方的事务上下文为基础,方法的事务属性会根据调用方是否存在事务来确定是否加入该事务。这样做的目的是为了确保事务的一致性和完整性,并让容器来管理事务的生命周期和边界。
================================
如果在调用 EJB 方法时存在一个事务,则容器会根据方法的事务属性来决定是加入已有事务还是创建一个新事务。具体来说:
- 如果方法的事务属性是
TransactionAttributeType.REQUIRED
,则会加入已有事务。- 如果方法的事务属性是
TransactionAttributeType.REQUIRES_NEW
,则会挂起当前事务并创建一个新事务。
==
3.WebSphere架构
・cell,node,server,app
基本结构:单元(cell) ——> 多个节点(node) ——> 多个服务(server) ——> 多个应用(app)
WebSphere8集群配置_websphere集群配置共享库_chjttony的博客-CSDN博客
・单元Cell:整个分布式网络中一个或多个节点的逻辑分组,是一个管理上的概念, 是管理员将节点间逻辑关联起来的实现方法, 可以将单元看作是WAS最大的作用域
・节点Node:是受管服务器(Server)的逻辑分组, 节点通常与具有唯一IP主机地址的逻辑或物理计算机系统对应, 节点不能跨多台计算机,它也是管理使用上的概念
・服务Server:Application Server Instance,即实际部署应用的地方,在ND版本中一个节点可能有多个Server,但非ND版本(Single Server版本),一个节点只能使用一个Server
・Cluster
对WebSphere中Cell、Node、Server、Node Agent、Cluster 的理解_websphere cluster_仁王_雅治的博客-CSDN博客
・Cluster(集群)是一组Server的集合,通常这些Server在一起处理同一类业务请求。集群负责平衡服务器之间的工作负载。当在集群上安装应用程序时,会在每个集群成员上自动安装此应用程序。
===
・webSphere cluster 介绍
==
WebSphere Cluster是IBM WebSphere Application Server的高可用性解决方案,它是一组WebSphere Application Server实例的集合,这些实例在不同的物理服务器或虚拟机上运行。它通过将请求分配到运行相同应用程序的多个服务器来提高应用程序的可用性和性能。当一个服务器出现故障时,请求会自动转移到另一个服务器上,从而保证了应用程序的连续性和可靠性。WebSphere Cluster还提供了负载均衡和故障转移等高级功能,以确保应用程序始终处于最佳状态,并能够满足大量用户的需求。
==
・webSphere 动态 Cluster
==
WebSphere 动态 Cluster 是一种 WebSphere 应用服务器集群的类型,它具有动态配置和自我管理的能力。在动态 Cluster 中,WebSphere 应用服务器可以自动加入或退出集群,而无需手动配置。这种集群类型可增加应用服务器的可用性和扩展性,同时减少了手动配置的工作量。
===
动态 Cluster 的核心是一个控制器节点,该节点负责协调集群中的应用服务器。此控制器节点可以通过 WebSphere 控制台进行配置。在动态 Cluster 中,集群中的应用服务器可以通过自我注册和注销来管理自己的状态。此外,动态 Cluster 还具有自我平衡的能力,可以自动将负载分配到可用的应用服务器上。
===
总之,动态 Cluster 是一种高度自动化和可扩展的 WebSphere 应用服务器集群类型,它可以提高应用服务器的可用性和性能,并减少手动配置的工作量。
====
・websphere 一个Cluster配置了多个node,实现了负载平衡,但是如何访问这个Cluster对应的虚拟主机的IP地址
要访问一个WebSphere Cluster对应的虚拟主机IP地址,你可以使用Web服务器或反向代理服务器,例如IBM HTTP Server或Apache HTTP Server。你可以将Web服务器配置为将请求路由到Cluster中的不同节点,以实现负载平衡。在Web服务器中,你需要将Cluster配置为一个Web服务器插件,并将Web服务器与Cluster中的每个节点进行通信。然后,你可以使用Web服务器的虚拟主机IP地址来访问Cluster中的应用程序。
====
・在Web服务器中配置WebSphere中的Cluster需要完成以下步骤:
1.确保WebSphere中已经创建了Cluster,并且Cluster中已经添加了应用程序。
2.在Web服务器中,打开配置文件,找到WebSphere插件的配置段落。
3.在配置段落中,找到WebSphereCluster的部分。
4.在WebSphereCluster部分中,添加以下配置信息:
WebSphereCluster ClusterName
ConnectTimeout 15
RetryInterval 60
ServerIOTimeout 900
<Server ServerName>
HostName WebSphereServerHostName
Port WebSphereServerPort
</Server>
</WebSphereCluster>
其中,ClusterName是WebSphere中Cluster的名称,ServerName是WebSphere中服务器的名称,WebSphereServerHostName是WebSphere服务器的主机名,WebSphereServerPort是WebSphere服务器的端口号。
5.保存配置文件并重启Web服务器。
完成以上步骤后,Web服务器就可以将用户请求路由到WebSphere中的Cluster中了。
===
4.WebSphere常用功能呢
【システム管理】
・查看部署的主机的信息
一个节点下面,有多个Node (ノード)
一个Node, 对应i1个【XXXXCell_XXX_dmger】,即DM(Deployment Manager)
一个Node, 对应多1个主机(Host)
一个Node(1个主机), 对应多个 服务(Server)
【システム管理】----【Cell】【Node】【Host】
⇒セル
└ノード
└XXXXCell_XXX_dmgr
└XXXXCell_node01
└XXXXCell_node02
★ 在这个,可以查看节点对应的 【host名】
自己安装的WebSphere(docker 镜像 启动的容器),里面没有找到Cell
====
【セキュリティ】【証明書】
・客户端证明书
・セキュリティ
└SSL証明書および鍵管理
└エンドポイント・セキュリティ構成の管理
インバウンド
XXXCell
nodes
XXXnodes
XXXnodes
XXXnodes●Servers
XXX Servers1
XXX Servers2
XXX Servers3
clusters
XXXCluster
XXXCluster
XXXCluster
アウトバウンド
XXXCells
nodes
XXXnodes
XXXnodes
XXXnodes
clusters
XXXCluster
XXXCluster
XXXCluster●⇒鍵ストアおよび証明書
└CellDefaultKeyStore
└CellDefaultTrustStore
└NodeDefaultKeyStore ?
└NodeDefaultTrustStore●●
●●⇒個人証明書
===
===
====================
【故障检修】【トラブルシューティング】
・查看Cell,Node,Server的构造--- 【树形结构】
【トラブルシューティング】 ( trouble shooting 故障检修)
⇒クラス・ローダー・ビューアー
⇒XXXCell
└【ノード】
└XXX Node1
└【サーバー】
└XXX Server1
└XXX Server2
└XXX Node2
・查看jar加载顺序
websphere7.0 jar包冲突解决办法,类加载顺序-蒲公英云
【トラブルシューティング】 // 故障检修
⇒クラス・ローダー・ビューアー
⇒Cell
⇒ノード
⇒サーバー
⇒XXXServer
⇒アプリケーション
⇒YourApplication
⇒ClassLoader - 検索順序
1.
2.
3.
4.
..
n.工程的目录 // 工程的下面的jar是最后被加载的。
シューティング 【名】【英】shooting 射击
==============================
【アプリケーション】【Application】
・查看Application的数据源 (比如 JNDI)
【アプリケーション】
⇒すべてのアプリケーション
⇒YourApplicationName
javax.sql.DataSource
【ターゲット・リソースJNDI名】的部分
//jdbc/xxxDB // 可以在数据源配置中,查到这个
【リソース参照】的部分
//jdbc/xxxSchema // 在数据源配置中,查不到这个,是数据库的Schema
・查看Application的EJB
【アプリケーション】
⇒すべてのアプリケーション
⇒YourApplicationName
⇒ビジネス・インターフェースを持つエンタープライズBean
( ↑ ★ EJB中的各个方法,都是一个事务,中间处理出错,可以回滚 ★)
・查看Cluster
【アプリケーション】
⇒すべてのアプリケーション
⇒YourApplicationName
└ターゲット特定アプリケーションの状況
↑ここで、所属のClusterが表示あれる。xxxClusterX
・查看所有的Application
【アプリケーション】
⇒すべてのアプリケーション
⇒YourApplicationName
⇒XXX。。。
↑ 部分Application在这里并没有显示
⇒アプリケーション・タイプ
⇒WebSphere エンタープライズ・アプリケーション
⇒YourServerName
⇒XXX。。。
↑ 这里可以查看所有的Application
・查看所有的Application部署的位置(Context root) 上下文
【アプリケーション】
⇒アプリケーション・タイプ
⇒WebSphere エンタープライズ・アプリケーション
⇒YourServerName
⇒「Web モジュールのコンテキスト・ルート」
↑ 可以看到Context root情报「/xxx/」路径
===
===
【WebSphere 中的 Context root】
WebSphere 中的 Context root 是指 Web 应用程序在 Web 服务器中的根上下文路径。它是 Web 应用程序的 URL 路径的一部分,用于定位 Web 应用程序的资源,例如 HTML 页面、CSS、JavaScript、图像等。
===
在 WebSphere 中,Context root 可以在应用程序部署时指定,也可以在应用程序的 web.xml 文件中配置。在应用程序部署后,可以通过 WebSphere 的管理控制台来查看和修改 Context root。
===
Context root 的设置对于应用程序的访问非常重要,因为它确定了 Web 应用程序的 URL。例如,如果 Context root 被设置为 "/myapp",则 Web 应用程序的 URL 将是 "http://localhost:9080/myapp"。
===
====
・查看Application发布的位置
【アプリケーション】
⇒アプリケーション・タイプ
⇒WebSphere エンタープライズ・アプリケーション
⇒YourServerName
⇒詳細プロパティー⇒アプリケーション・バイナリ
↑ * ロケーション(絶対パス)
【/Apl/XXSystem/installedApps/】
===
这个是一个自带的Ejb的Application,没有上下文
==
===
・配布した後の資材の構造 (赤字は固定)
/Apl/XXSystem/installedApps
└YourEarName-editionYourEditionName.ear
└META-INF
└YourEarName.war
└META-INF
└persistence.xml // (JPAの配置ファイル)
└WEB-INF
└classes
└lib
└*.xml
・查看引用的资源文件(配置文件)
【アプリケーション】
⇒アプリケーション・タイプ
⇒WebSphere エンタープライズ・アプリケーション
⇒YourServerName
⇒参照⇒リソース参照
==============================
【リソース】
・指定配置文件(资源文件)的位置
【リソース】 (指定配置文件(资源文件)的位置)
└URL
xxxx.properties ファイル Location
file:///AAA/BBB/xxxx.properties
===
==============================
【服务】【サーバー】
・查看Server,Node,Cluster的构造--- 【一览表】
可以通过 在【アプリケーション】找到的 xxxClusterX,在这里找到对应的 xxxxServer X
サーバー
⇒すべてのサーバー
显示了下面的信息==============
名前(Server)、ノード、クラスター名、状況、保守モード、バージョン、。。。xxxxServer X xxxClusterX
==============
====
・查看Server的JDK版本
【サーバー】
⇒すべてのサーバー
⇒YourServerName
⇒Java SDK
===
・查看Server的端口号
【サーバー】
⇒すべてのサーバー
⇒YourServerName
⇒通信
⇒ポート
⇒WC_defaulthost(应用程序访问端口)
・查看Server上面部署的App
【サーバー】
⇒すべてのサーバー
⇒YourServerName
⇒インストール済みアプリケーション
(一个Server上面,可以部署多个App,多个App使用同一个端口号)
10.123.123.126:12006/web1
10.123.123.126:12006/web2
10.123.123.126:12006/web3
・查看Server上面部署的App的资源情报(比如 JNDI)
【サーバー】
⇒すべてのサーバー
⇒YourServerName
⇒インストール済みアプリケーション
⇒YourApplicationName⇒リソース参照
└「javax.sql.DataSource 」的部分
└【リソース参照】的部分
//jdbc/xxxSchema // 在数据源配置中,查不到这个,是数据库的Schema
└【ターゲット・リソースJNDI名】的部分
//jdbc/xxxDB // 可以在数据源配置中,查到这个
・查看Server的Access_Log相关配置
=======
AccessLog位置定義場所:
アプリケーション・サーバー > Your ServerXXX > NCSAアクセス・ロギングおよびHTTPエラー・ロギング
------------------
format定義場所:
アプリケーション・サーバー > Your ServerXXX > Webコンテナー・ドランスポート・チェーン > WCInboundDefault > HTTP インバウンド・チャネル(HTTP 2) > カスタム・プロパティー(コンテナー設定 ⇒ Webコンテナー設定 ⇒ Webコンテナー・ドランスポート・チェーン )
=======属性的名字【accessLogFormat】,值的内容如下%t %h %{iv-user}i [ %{Referer}i ] %u %t "%r" %s %b %D"
--------------
pattern="%h %l %u %t "%r" %s %b %D"=======
Here are some common placeholders:
%h: Remote host IP address
%l: Remote logical username
%u: Remote user that was authenticated (if any)
%t: Date and time in the format [dd/MM/yyyy:HH:mm:ss Z]
%r: First line of the request
%s: HTTP status code
%b: Bytes sent, excluding HTTP headers
%D: Time taken to process the request, in milliseconds
不是 毫秒(milliseconds),是微妙
===iv-user // IBM
===
・查看Server的访问限制(比如Post请求的最大size)
xxx
アプリケーション・サーバー > Your ServerXXX >
====================================================
【コンテナー設定】
┠XXXX
┠【Webコンテナー設定】
┠XXXX
└【Webコンテナー・ドランスポート・チェーン】
┠。。。。。===================================================
管理できるリソース ||。。。。。。。|| ピート
XXXXSXX ||。。。。。。。|| 17070(YourServer Port)
↓
===================================================HTTP インバウンド・チャネル(HTTP 2)
↓
===================================================
サービス妨害からの保護
32768 バイト
(这是一个默认值,默认都是 32K)
这里应该只是限制 Header的长度,不限制Body的长度,比如一个请求,JSON 数据的 大小是 20M,这里是拦截不住的!!!
===================================================
===
===
===
====
====
■5.WebSphere 错误调查
==== 此错误产生原因 =====
■1.16.WebSphere中,对于 JAP的实现,每次查询之后,还要根据主键,再查询一次(坑!!!)
在实体类中使用了@Id注解来定义主键,那么每次查询后都会自动根据主键再查询一次。
5.1. Failed to load webapp: Context root /xxx/***
Caused by: com.ibm.ws.webcontainer.exception.WebAppNotLoadedException: Failed to load webapp: Context root /xxx/*** is already bound. Cannot start application ideal。
原因:
Application中,「コンテキスト・ルート」这里、可以查看路径「/xxx/」
有别的Application也使用了这个「/xxx/」路径。
停止占用了这个「コンテキスト・ルート」的Application即可。
===
5.2.openjpa-2.2.3-SNAPSHOT-r422266:1764177 nonfatal store error
└org.apache.openjpa.persistence.EntityNotFoundException
前言:新增了一个EJB
===
org.apache.openjpa.persistence.EntityNotFoundException
タイプ "xxxxx.xxxx.xxxx.XXXEntity"、oid "A12345" のインスタンスは、データ・ストアにもう存在していません。これは別のトレサビリティでそのインスタンスを削除したが、キャッシュされたものがこのコンテキストにまだ含まれることを意味している可能性があります。
FailedObject:xxxxx.xxxx.xxxx.XXXEntity-A12345
oid "A12345" : 是查询的表的主键的值。
=====
原因:执行了2次查询,
第一次查询时,使用的是代码的SQL (Schema666),对应的表中有数据。
第二次查询,是框架自己的查询 (Schema Default),对应的表中,没有数据。
所以,在错误信息中,才会出现事务相关的信息。
(临时解决:
发布时,对应数据库关联的 Entity, 指定Schema666,这样第二次查询时,和第一次查询时,就是同一个Schema了。
@Table(name=“xxxxx”, schema="Schema666"))
=====
===
尝试解决1:(看看有没有主表,子表直接的关系。)
=== === === === === === === ===
javax.persistence.EntityNotFoundException: Unable to find 某个类 with id
原因:无论是@OneToOne 还是@ManyToOne,出现这个原因都是因为子表(被关联表)中没有主表(关联表)中ID所对应的记录。
解决办法:
检查为什么子表中没有主表中ID对应的记录
如果子表中没有主表ID对应的记录也可以正常加载数据,那么需要在主表字段上加一个@NotFound Annotation。示例如下:
@OneToOne(optional=true )
@JoinColumn(name="UserId ",insertable=false, updatable=false)
@NotFound(action=NotFoundAction.IGNORE)
private UserId userId;这样,当子表中没找到数据时,主表中对应的field就是null,而不会报错了。
尝试失败,定义的表结构,根本没有主表,子表的关联。
补足说明:主表和子表
====
补足说明:DB2中,创建外键约束
-- 创建测试主表. ID 是主键.CREATE TABLE test_main ( id INT NOT NULL, value VARCHAR(10), PRIMARY KEY(id) );
-- 创建测试子表. CREATE TABLE test_sub ( id INT NOT NULL, main_id INT , value VARCHAR(10), PRIMARY KEY(id) )-- 插入测试主表数据.INSERT INTO test_main(id, value) VALUES (1, 'ONE');INSERT INTO test_main(id, value) VALUES (2, 'TWO');
-- 插入测试子表数据.INSERT INTO test_sub(id, main_id, value) VALUES (1, 1, 'ONEONE');INSERT INTO test_sub(id, main_id, value) VALUES (2, 2, 'TWOTWO');默认外键约束方式
db2 => ALTER TABLE test_sub ADD CONSTRAINT main_id_cons FOREIGN KEY (main_id) REFERENCES test_main;
=== === === === === === === ===
尝试解决2:
=================================
下面的链接中,虽然出现的和我是同样的错误,但是,他的错误应该是子表造成的。
java - OpenJPA : Cascade Delete issue - Stack Overflow
===
//Parent
@Entity
@Table(name = "PARENT")
public class Parent implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "PRIMARY_ID", updatable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer primaryID;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, targetEntity = Child.class)
private List<Child> child;
//Child
@Entity
@Table(name = "CHILD")
public class Child implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private ChildPK id;
@MapsId("primaryID") //Maps to primaryID in ChildPK
@ManyToOne
@JoinColumn(name = "PRIMARY_ID",nullable=false)
private Parent parent;
public Child() {
}
===
public static void main(String[] args) {
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("jpa-test");
EntityManager entityManager = entityManagerFactory.createEntityManager();
Parent parent = entityManager.find(Parent.class, 15149);
entityManager.getTransaction().begin();
entityManager.remove(parent);
entityManager.getTransaction().commit();
}
===
下面只是一个类似的例子,我本次遇到的问题,并没有出现【RollbackException】异常
Exception in thread "main" <openjpa-2.2.3-SNAPSHOT-r422266:1715851 fatal store error> org.apache.openjpa.persistence.RollbackException: The transaction has been rolled back. See the nested exceptions for details on the errors that occurred.
FailedObject: com.entity.test.Parent -15149
at org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:594)
at com.test.Test.main(Test.java:76)
Caused by: <openjpa-2.2.3-SNAPSHOT-r422266:1715851 fatal general error> org.apache.openjpa.persistence.PersistenceException: The transaction has been rolled back. See the nested exceptions for details on the errors that occurred.
FailedObject: com.entity.test.Parent-15149
at org.apache.openjpa.kernel.BrokerImpl.newFlushException(BrokerImpl.java:2352)
at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2189)
at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2087)
==========================================
最终解决1:
更换了一个IT环境,问题就解决了。。。(并非彻底解决,之前的一个环境废掉了。。。)
最终解决2:清空缓存
/xxx/yourInstallFolder/WebSphere/AppServer/profiles/yourWebSphereApplication/config/cells/YourCellName/applications/yourApplicationName
删除:yourApplicationName 目录,重新启动WebSphere的Application,问题解决
===
5.3.org.apache.openjpa.lib.jdbc.ReportingSQLException
前言:在数据库中,添加了几个字段,然后新增查询,更新处理。
===
org.apache.openjpa.lib.jdbc.ReportingSQLException: 使用されているコンテキストで、"T0.NewColumn"は無効です。. SQLCODE=-206,SQLSTATE=42703.
"NewColumn" :テーブルで、新規追加のColumn
com.ibm.db2.jcc.am.SqlException:。。。エラー関連えて戻された情報 SQLCODE=-206,SQLSTATE=42703. およびメッセージトークン "XXXXX_ID"が含まれています。.SQLCODE=-727,SQLSTATE=56098.
===
下面这篇文字也是类似的错误。(但是我新增的字段,都是用大写定义的呀!)
DB2 SQLCODE=-206, SQLSTATE=42703 定义表字段问题_sqlcode -206_dearbaba_8520的博客-CSDN博客
"STATUS" is not valid in the context where it is used.. SQLCODE=-206, SQLSTATE=42703, DRIVER=3.53.71
更多例外 ... An error occurred during implicit system action type "2". Information returned for the error includes SQLCODE "-206", SQLSTATE "42703" and message tokens "STATUS".. SQLCODE=-727, SQLSTATE=56098, DRIVER=3.53.71
======
执行SQL文时总是报这个错误,原因是:
在DB2中,默认情况下所有的名称都可包含一下字符:A-Z(大写) 0到9 @、#、$和_(下划线) 名称不能以数字和下划线开头。
数据库对象的表,其命名遵循以上规则,所以即使利用命令创建表时,使用的是小写,DB2仍会将其转换为大写。
但需要注意的是,并非db client软件也会自动转换,我在使用ibm data studio4或Aqua data studio等客户端时,发现统计studio 提供的图形界面创建,并不能自动转换为大写,
比如使用studio创建表时将字段定义为小写的status,这样再使用普通的SQL语句操作,例如:
select * from LARGE_RECEIPT where status='E' 就会报错
解决方法:定义时用大写字母
=====
【TODO】解决:。。。
5.4.XXX
xxx
5.5.XXX
xxx
【数据源】【データ・ソース】
・配置1
websphere环境下JPA多对多时关闭result set-百度经验
・配置2:【WebSphere中 查看数据源使用的数据库用户】
要在WebSphere中查看数据源使用的数据库用户,请按照以下步骤操作:
登录WebSphere控制台。
===
导航到“数据源”>“数据源名称”>“进一步属性”>“J2C身份验证数据”。===
查找“用户ID”字段。此字段将显示数据源使用的数据库用户。===
请注意,此方法取决于您设置数据源时选择的身份验证类型。如果您选择了“容器管理身份验证”,则WebSphere将使用应用程序服务器的身份验证上下文来连接到数据库。在这种情况下,您将无法在WebSphere控制台中查看数据源使用的数据库用户。
========================
■6.各种目录
6.1.缓存目录(实际运行目录)
/app/WebSphere/AppServer/profiles/AppSrv01/config/cells/YDZYTNode01Cell/applications/yourApplicationName
/xxx/yourInstallFolder/WebSphere/AppServer/profiles/yourWebSphereApplication/config/cells/YourCellName/applications/yourApplicationName
===
/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/config/cells/DefaultCell01
===
6.2.配置文件目录
=====
/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/config/cells/DefaultCell01/nodes/DefaultNode01
=======
/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/config/cells/DefaultCell01/nodes/DefaultNode01/servers/server1
====
6.3.启动Log目录
/Logs/IMB/was/YourCell/YourServer/SystemOut.log
6.4.XXX
xxx
6.5.XXX
xxx
6.6.XXX
=====
7.工程相关的资源
●设定方式1:共有ライブラリー設定
・共有ライブラリー設定 (指定)
【アプリケーション】
⇒すべてのアプリケーション
⇒YourApplicationName
⇒共有ライブラリー参照
选择【モジュール】 (对应的资源是「xxxx.war」)
之后,点击按钮【参照共有ライブラリー】
⇒进入页面之后,选择 对应的 「ライブラリー」
===
===
・共有ライブラリー設定 (设定)
【環境】
⇒共有ライブラリー
⇒有効範囲選択(利用のApplication所属のClusterを選択する。)
⇒【新規作成】
⇒在画面中,设定如下项目
・名前
・クラスパス
└/xxx/xxx/xx/properties
(一些配置文件,比如log4j,jdbc,properties等文件,可以放在这里)
===
==
●设定方式2:リソース参照
・ソースのProject側 (設定) web.xml
<resource-ref>
<res-ref-name>xxx
<res-type>java.net.URL</res-type>
</resource-ref><resource-ref>
<res-ref-name>xxx
<res-type>javax.sql.DataSource</res-type>
</resource-ref>
・Ear读取的xxxx.properties文件目录指定 (設定)
对应上面的:java.net.URL
(上面的javax.sql.DataSource 要在数据源中,设定相应的配置)
【リソース】
⇒URL
⇒URL
⇒有効範囲選択(利用のApplication所属のClusterを選択する。)
⇒【新規作成】
⇒在画面中,设定如下项目
・名前
・JNDI名
・仕様(資材のパス)
・Ear读取的xxxx.properties文件目录指定 (設定)
===
===
・Ear读取的xxxx.properties文件目录指定 (指定)
【アプリケーション】
⇒すべてのアプリケーション
⇒YourApplicationName
⇒リソース参照
在这里可以看到web.xml中指定的下面两项
・java.net.URL
・javax.sql.DataSource
8.状态是「使用不可」的Application,如何启动
状态是「使用不可」的Application是无法启动的,一览中,对应都图标是一个「禁止符号:🚫」
【アプリケーション】
⇒ エディション・コントロール・センター
选择你的Application的名字,点击进入
⇒选择你的Application的想有效化的Edition,然后点击「アクティブ化」Button
===
9.WebSphere官方文档
9.1.关于JPA
JPA for WebSphere Application Server - IBM Documentation
===
9.2.IBM--JPA--API--文档
Overview (IBM WebSphere Application Server XML API Javadoc, Release 8.5)
9.3.xxx
xxx
===
10.OpenJPA官方文档
https://openjpa.apache.org/builds/2.2.2/apache-openjpa/docs/main.html
6. OpenJPA JDBC Properties
└6.12. openjpa.jdbc.Schema
===
11.其他
11.1.在 WebSphere中 rollout是什么意思
在WebSphere中,rollout指的是将一个新的应用程序或应用程序的新版本推出到生产环境中。这包括在部署环境中安装和配置应用程序,确保它正确运行,并在生产环境中向用户提供服务。Rollout的过程通常涉及许多步骤,如将应用程序文件复制到目标服务器,配置服务器和数据库连接,启动应用程序,进行测试和验证等。它是将新版本应用程序从开发环境或测试环境推出到生产环境的重要步骤。
===
11.2.
===
11.3.
====
12.奇怪的错误
奇怪的错误1
・错误现象
使用 JPA 查询数据,报错,
错误信息提示,java的日期类型 和 String 类型转换错误。Caused by: <openjpa-2.2.3-SNAPSHOT-r422266:1764177 nonfatal store error>
org.apache.openjpa.persistence.PersistenceException: java.long.String incompatible with java.util.Date
・错误分析
SQL 在 DB2 中能正常执行。
查看代码,也没有任何问题。・错误解决
重新启动WebSphere后,错误解决・问题直接原因(2024/04/09记入)
同一个表,定义了多个Entity,
并且不同Entity中,字段的类型不一样(有的是【String】 有的 是 【日期类型】)
・问题根本原因
未知
奇怪的错误2
・错误现象
一个字段是 varchar(5) default ''
使用JPA插入,插入时使用默认值,数据插入后,
期待值是空字符串,但实际,竟然变成了5个空格。・错误分析
使用SQL 往DB库中插入,使用默认值,是空字符串。
查看代码,也没有任何问题。・错误解决
把整个表删掉,重新创建表后,问题解决。
===
13.常见错误
1.查询不到数据---因为表是复合主键
现象:报错,查询不到数据
错误信息
<openjpa-2.2.3-SNAPSHOT-r422266:1764177 fatal general error> org.apache.openjpa.persistence.PersistenceException:[jcc][t4][10145][10897][4.28.11]パラメーター 0 が無効:パラメーター索引が範囲外です。ERRORCODE=-4461, SQLSTATE=42815
解决(复合主键设定):
1.【新定义一个】TableNameId.java类(主键的Bean),
・在里面定义2个主键
・在Bean中的两个主键项目,都加上@Id
2.找到,在Dao中使用的Bean中。(Table对应的Bean)
3.在Bean中使用如下代码 (添加下面第一行代码)
@IdClass(TableNameId.class)
@Table(name = "YourTableName")
public class YourTableName {。。。
=================
解决(其它问题):
1.Dao中使用的Bean(Table对应的Bean( YourTableName.class ))要统一,是一个!
2.select xxxxx项目1 ,xxxx项目2 from schemaXX.TableName // 【项目XX】里面一定要有主键!!! 主键 是表 YourTableName.class 的主键
EntityManager em;
List<YourTableName> list = em.createNativeQuery("select xxxxx项目1 ,xxxx项目2, xxx from xxxTable where xxx='xxx' ", YourTableName.class )
.setParameter(1, param1)
.getResultList();
===补足说明1
在实体类(YourTableName.class)中使用了@Id注解来定义主键,那么每次查询后都会自动根据主键再查询一次(查询的条件是,之前查询到的结果集中的主键项目,也许这就是为什么 【项目XX】里面一定要有主键!!! 的原因)。
坑:这个时候再次查询时,使用默认的Schema
====
===补足说明2
查询时,可以使用表连接查询多个表,
YourTableName left join YourTableNam666
只要抽出的项目中,没有 【YourTableNam666】表中的项目,代码就可以正常运行,
此时,也会再查询一次,但也仅对【YourTableNam】再查询一次,不会对【YourTableNam666】再查询一次。(再次 查询对象表 应该和 YourTableName.class 的指定有关)
List<YourTableName> list = em.createNativeQuery("select xxxxx项目1 ,xxxx项目2, xxx YourTableName left join YourTableNam666 on xx=xx where xxx='xxx' ", YourTableName.class )
===
2.查询不到数据---返回值不是List 是一个单独的Bean
现象:查询数据时报错
解决:
原因未知
====
14.查询核心【javax.persistence.EntityManager】
・注入使用
@PersistenceContext(unitName = "xxxxdb")
private EntityManager em ;
・API
EntityManager (Java(TM) EE 7 Specification APIs)
====
常用方法
・Query createNativeQuery(String sqlString) // 根据SQL文,返回对象
・Query createNativeQuery(String sqlString, Class resultClass) // 根据SQL文,返回对象
・<T> T find(Class<T> entityClass, Object primaryKey) // 根据主键,直接返回整个对象, 无需在SQL文中定义每一个项目
=====