这个问题可以看作是Hibernate悲观锁定不适用于多态查询的后续问题
让我们考虑一个比问题更简单的情况:两个实体A和B,其中B继承于A,两者都是具体的类。
我使用的PostgreSQL驱动程序不支持外部联接和FOR SHARE/FOR UPDATE的组合。
我什么时候做
sessionManager.get(A.class, id, new LockOptions(PESSIMISTIC_READ)));
我将在逻辑上产生错误:
ERREUR: FOR SHARE ne peut ?e appliqu?ur le c??possiblement NULL d'une jointure externe
这是我之前说的法语版本。
我可以这样从技术上“解决”这个问题:
A a = (A) sessionManager.get(B.class, id, new LockOptions(lockMode));
if(a== null) {
return (A) sessionManager.get(A.class, id, new LockOptions(lockMode));
}else {
return a;
}
但是你可以理解我在这方面有个问题。
虽然我不确定是否能够在当前项目中做得更好,但我想知道问题出在哪里:
如果有什么区别的话,这是PostgreSQL(10)、Hibernate(5.4.3)和驱动程序(42.2)的最新版本。使用的方言是PostgreSQL10方言。
我按照@ChristianBeikov的建议升级到Hibernate 5.4.31,我不再有这个问题了。
以下是升级前重现问题的代码:
pom.xml
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>hibernate.test</groupId>
<artifactId>test-outer-join-null</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.23.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.13.RELEASE</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.9</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>9.0.1</version>
</dependency>
</dependencies>
@Configuration
@ComponentScan(basePackages = {"hibernate.test.service"})
@EnableTransactionManagement
public class HibernateConf {
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan("hibernate.test");
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://127.0.0.1:5432/test");
dataSource.setUsername("test");
dataSource.setPassword("test");
return dataSource;
}
@Bean
public PlatformTransactionManager hibernateTransactionManager() {
HibernateTransactionManager transactionManager
= new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
private final Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty(
"hibernate.hbm2ddl.auto", "update");
hibernateProperties.setProperty(
"hibernate.show_sql", "true");
hibernateProperties.setProperty(
"hibernate.dialect", "org.hibernate.dialect.PostgreSQL10Dialect");
return hibernateProperties;
}
}
----实体 ------
@Entity(name = "test_a")
@Inheritance(strategy = InheritanceType.JOINED)
public class A {
@Id
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public A() {
super();
}
public A(int id, String name) {
this.id = id;
this.name = name;
}
}
@Entity(name = "test_b")
@Inheritance(strategy = InheritanceType.JOINED)
public class B extends A{
@Column(name="last_name")
private String lastName;
public String getLastName() {
return lastName;
}
public void setLastName(String name) {
this.lastName = name;
}
public B() {
super();
}
public B(int id, String name, String lastName) {
super(id, name);
this.lastName = lastName;
}
}
------ 服务
public interface IService {
public void init();
<T extends A> void listCriteria(Class<T> theClass);
}
@org.springframework.stereotype.Service
public class Service implements IService{
@Autowired
SessionFactory sessionFactory;
@Override
@Transactional
public void init() {
Session session = sessionFactory.getCurrentSession();
A a = new A((int)Math.round(Math.random()*1000000), "a");
B b = new B((int)Math.round(Math.random()*1000000), "a", "b");
session.persist(a);
session.persist(b);
}
@Override
@Transactional
public <T extends A> void listCriteria(Class<T> theClass) {
Session session = sessionFactory.getCurrentSession();
T t = session.get(theClass, 3, LockMode.PESSIMISTIC_WRITE); // <---- the error happens HERE
System.out.println(t);
}
}
------主要------
public static void main(String[] args) {
try(AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(HibernateConf.class)){
IService manager = context.getBean(IService.class);
manager.init();
manager.list(A.class);
manager.listCriteria(A.class);
System.out.println("====================");
manager.list(B.class);
manager.listCriteria(B.class);
}
}
问题内容: 当我尝试编译时,它给了我错误 我应该如何解决这个问题? 问题答案: 该错误是由于以下事实导致的:调用将是不明确的- 应该调用两种方法中的哪一种?从JLS§8.4.2开始: 在类中声明两个具有重写等效签名的方法是编译时错误。 方法的返回类型不是其签名的一部分,因此根据上述说明,您将收到错误。 假设您不能简单地重命名冲突的方法,在这种情况下就不能使用继承,并且需要使用诸如compositi
我有一个简单的类,注释为 例如: 然后我有一个扩展这个bean的配置bean: 似乎忽略了有条件的,无论条件如何解决,都会始终处理配置(甚至没有调用) 只要我将有条件注释移动到MyConfig,一切都会正常工作。 从文档: @条件注释可以以下列任何一种方式使用: 作为使用@组件直接或间接注释的任何类的类型级注释,包括@配置类 我假设第一点适用于这里,即MyConfig间接地用配置注释。或者间接引用
问题内容: 我在使用Python进行面向对象的编程方面非常陌生,并且在理解函数(新样式类)时遇到困难,特别是在涉及多重继承时。 例如,如果你有类似的东西: 我不明白的是:该类会继承两个构造函数方法吗?如果是,那么哪个将与一起运行,为什么? 而如果要运行另一个呢?我知道这与Python方法解析顺序有关。 问题答案: Guido自己在他的博客文章(包括两次较早的尝试)中对此进行了合理的详细说明。 在你
处理 css 兼容性需要使用到 postcss-loader 和postcss-preset-env两个插件 一、css 兼容性处理核心配置 1.1、修改webpack.config.js 配置文件 // webpack.config.js webpack的配置文件 // 路径: ./webpack.config.js ………… // 设置 nodejs 环境变量 process.
我在抽象课上有以下内容... 还有另一个类,它继承了这个类... 当我从主类执行以下调用时,我收到一个错误... 我的问题是..为什么会发生这种情况?我的getEntityById不是返回T型的东西,在这种情况下应该是产品吗? 我在 Netbeans 中工作,编译时未显示任何错误。 感谢您的帮助=)
并尝试通过Hibernate使用策略连接实现继承,但当我使用此策略时,我收到异常: 奇怪的是,如果我选择另一个策略(单表或TABLE_PER_CLASS),错误不会出现