Viewed   423 times

With this configuration (MainConfig.java):

import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.jta.JtaTransactionManager;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;

@Configuration
@ComponentScan
public class MainConfig {

    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
        hibernateJpaVendorAdapter.setShowSql(true);
        hibernateJpaVendorAdapter.setGenerateDdl(true);
        hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);
        return hibernateJpaVendorAdapter;
    }

    @Bean(name = "userTransaction")
    public UserTransaction userTransaction() throws Throwable {
        UserTransactionImp userTransactionImp = new UserTransactionImp();
        userTransactionImp.setTransactionTimeout(10000);
        return userTransactionImp;
    }

    @Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")
    public TransactionManager atomikosTransactionManager() throws Throwable {
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        userTransactionManager.setForceShutdown(false);
        return userTransactionManager;
    }

    @Bean(name = "transactionManager")
    @DependsOn({ "userTransaction", "atomikosTransactionManager" })
    public PlatformTransactionManager transactionManager() throws Throwable {
        UserTransaction userTransaction = userTransaction();
        TransactionManager atomikosTransactionManager = atomikosTransactionManager();
        return new JtaTransactionManager(userTransaction, atomikosTransactionManager);
    }

}

(CustomerConfig.java)

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.at.mul.repository.customer", entityManagerFactoryRef = "customerEntityManager", transactionManagerRef = "transactionManager")
public class CustomerConfig {

    @Autowired
    private JpaVendorAdapter jpaVendorAdapter;

    @Bean(name = "customerDataSource", initMethod = "init", destroyMethod = "close")
    public DataSource customerDataSource() {
        MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
        mysqlXaDataSource.setUrl("jdbc:mysql://localhost:3306/atomikos_1");
        mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
        mysqlXaDataSource.setPassword("password");
        mysqlXaDataSource.setUser("root");
        mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);

        AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
        xaDataSource.setXaDataSource(mysqlXaDataSource);
        xaDataSource.setUniqueResourceName("xads1");
        return xaDataSource;
    }


    @Bean(name = "customerEntityManager")
    public LocalContainerEntityManagerFactoryBean customerEntityManager() throws Throwable {
        LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
        entityManager.setDataSource(customerDataSource());
        entityManager.setJpaVendorAdapter(jpaVendorAdapter);
        entityManager.setPackagesToScan("com.at.mul.domain.customer");
        entityManager.setPersistenceUnitName("customerPersistenceUnit");
        Properties properties = new Properties();
        properties.put("javax.persistence.transactionType", "JTA");
        entityManager.setJpaProperties(properties);
        return entityManager;
    }

}

(OrderConfig.java)

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.at.mul.repository.order", entityManagerFactoryRef = "orderEntityManager", transactionManagerRef = "transactionManager")
public class OrderConfig {

    @Autowired
    private JpaVendorAdapter jpaVendorAdapter;

    @Bean(name = "orderDataSource", initMethod = "init", destroyMethod = "close")
    public DataSource orderDataSource() {
        MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
        mysqlXaDataSource.setUrl("jdbc:mysql://localhost:3306/atomikos_2");
        mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
        mysqlXaDataSource.setPassword("password");
        mysqlXaDataSource.setUser("root");
        mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);

        AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
        xaDataSource.setXaDataSource(mysqlXaDataSource);
        xaDataSource.setUniqueResourceName("xads2");
        return xaDataSource;
    }


    @Bean(name = "orderEntityManager")
    public LocalContainerEntityManagerFactoryBean orderEntityManager() throws Throwable {
        LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
        entityManager.setDataSource(orderDataSource());
        entityManager.setJpaVendorAdapter(jpaVendorAdapter);
        entityManager.setPackagesToScan("com.at.mul.domain.order");
        entityManager.setPersistenceUnitName("orderPersistenceUnit");
        Properties properties = new Properties();
        properties.put("javax.persistence.transactionType", "JTA");
        entityManager.setJpaProperties(properties);
        return entityManager;
    }

}

(CustomerRepository.java)

import org.springframework.data.jpa.repository.JpaRepository;

import com.at.mul.domain.customer.Customer;

public interface CustomerRepository extends JpaRepository<Customer, Integer> {

}

(OrderRepository.java)

import org.springframework.data.jpa.repository.JpaRepository;

import com.at.mul.domain.order.Order;

public interface OrderRepository extends JpaRepository<Order, Integer> {

}

I get a NullPointerException on when running this test:

import javax.transaction.Transactional;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.at.mul.MainConfig;
import com.at.mul.domain.customer.Customer;
import com.at.mul.repository.customer.CustomerRepository;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MainConfig.class)
@Transactional
public class CustomerRepositoryTest {

    @Autowired
    private CustomerRepository customerRepository;

    @Test
    public void testCustomerConfig() {

    }

    @Test
    public void save() {
        Customer c = new Customer();
        c.setName("test-name");
        c.setAge(30);
        Customer cust = customerRepository.save(c);
        Assert.assertNotNull(cust.getId());
    }

}

The null object seems to be the transactionManager, so I suppose it's not properly injected. Relevant part of the stacktrace is here:

java.lang.NullPointerException
    at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.getStatus(JtaStatusHelper.java:76)
    at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.isActive(JtaStatusHelper.java:118)
    at org.hibernate.engine.transaction.internal.jta.CMTTransaction.join(CMTTransaction.java:149)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.java:1602)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.postInit(AbstractEntityManagerImpl.java:210)
    at org.hibernate.jpa.internal.EntityManagerImpl.<init>(EntityManagerImpl.java:91)
    at org.hibernate.jpa.internal.EntityManagerFactoryImpl.internalCreateEntityManager(EntityManagerFactoryImpl.java:345)
    at org.hibernate.jpa.internal.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:313)
    at sun.reflect.GeneratedMethodAccessor10.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.invokeProxyMethod(AbstractEntityManagerFactoryBean.java:388)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.java:541)
    at com.sun.proxy.$Proxy29.createEntityManager(Unknown Source)
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.doGetTransactionalEntityManager(EntityManagerFactoryUtils.java:285)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:227)
    at com.sun.proxy.$Proxy34.persist(Unknown Source)
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:369)

The pom file is here:

<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>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.0.0.RC5</version>
    </parent>

    <groupId>com.at.mul</groupId>
    <artifactId>mul-at</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>mul-at</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <url>http://repo.spring.io/libs-snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <url>http://repo.spring.io/libs-snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.12.4</version>
        </dependency>

        <dependency>
            <groupId>com.atomikos</groupId>
            <artifactId>transactions</artifactId>
            <version>3.9.3</version>
        </dependency>

        <dependency>
            <groupId>com.atomikos</groupId>
            <artifactId>transactions-jta</artifactId>
            <version>3.9.3</version>
        </dependency>

        <dependency>
            <groupId>com.atomikos</groupId>
            <artifactId>transactions-hibernate3</artifactId>
            <version>3.9.3</version>
            <exclusions>
                <exclusion>
                    <artifactId>hibernate</artifactId>
                    <groupId>org.hibernate</groupId>
                </exclusion>
            </exclusions>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

Full code is available on Github: https://github.com/fabiomaffioletti/mul-at I could not find any working example, and even after looking at the Spring blog article I cannot get it to work. Has anyone any hint?

Following the console log of spring boot for the customer connection:

2014-04-01 11:29:48.645  INFO 22368 --- [           main] c.atomikos.jdbc.AbstractDataSourceBean   : AtomikosDataSoureBean 'xads1': init...
2014-04-01 11:29:48.645  WARN 22368 --- [           main] c.atomikos.jdbc.AbstractDataSourceBean   : AtomikosDataSoureBean 'xads1': poolSize equals default - this may cause performance problems!
2014-04-01 11:29:48.672  INFO 22368 --- [           main] c.atomikos.jdbc.AtomikosDataSourceBean   : AtomikosDataSoureBean 'xads1': initializing with [ xaDataSourceClassName=null, uniqueResourceName=xads1, maxPoolSize=1, minPoolSize=1, borrowConnectionTimeout=30, maxIdleTime=60, reapTimeout=0, maintenanceInterval=60, testQuery=null, xaProperties=[], loginTimeout=0, maxLifetime=0]
2014-04-01 11:29:48.809  INFO 22368 --- [           main] c.a.icatch.imp.thread.TaskManager        : THREADS: using JDK thread pooling...
2014-04-01 11:29:48.837  INFO 22368 --- [           main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'customerPersistenceUnit'
2014-04-01 11:29:48.857  INFO 22368 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [
    name: customerPersistenceUnit
    ...]
2014-04-01 11:29:48.919  INFO 22368 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate Core {4.3.1.Final}
2014-04-01 11:29:48.920  INFO 22368 --- [           main] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found
2014-04-01 11:29:48.922  INFO 22368 --- [           main] org.hibernate.cfg.Environment            : HHH000021: Bytecode provider name : javassist
2014-04-01 11:29:49.057  INFO 22368 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {4.0.4.Final}
2014-04-01 11:29:49.086  INFO 22368 --- [           main] c.atomikos.jdbc.AbstractDataSourceBean   : AtomikosDataSoureBean 'xads1': getConnection ( null )...
2014-04-01 11:29:49.087  INFO 22368 --- [           main] c.atomikos.jdbc.AbstractDataSourceBean   : AtomikosDataSoureBean 'xads1': init...
2014-04-01 11:29:49.145  WARN 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: WARNING: transaction manager not running?
2014-04-01 11:29:49.145  INFO 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: calling getMetaData...
2014-04-01 11:29:49.166  INFO 22368 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
2014-04-01 11:29:49.172  WARN 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: WARNING: transaction manager not running?
2014-04-01 11:29:49.172  INFO 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: calling getCatalog...
2014-04-01 11:29:49.174  WARN 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: WARNING: transaction manager not running?
2014-04-01 11:29:49.175  INFO 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: calling getMetaData...
2014-04-01 11:29:49.175  WARN 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: WARNING: transaction manager not running?
2014-04-01 11:29:49.175  INFO 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: calling createClob...
2014-04-01 11:29:49.177  WARN 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: WARNING: transaction manager not running?
2014-04-01 11:29:49.177  INFO 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: close()...
2014-04-01 11:29:49.258  INFO 22368 --- [           main] o.h.h.i.ast.ASTQueryTranslatorFactory    : HHH000397: Using ASTQueryTranslatorFactory
2014-04-01 11:29:49.428  INFO 22368 --- [           main] org.hibernate.tool.hbm2ddl.SchemaUpdate  : HHH000228: Running hbm2ddl schema update
2014-04-01 11:29:49.428  INFO 22368 --- [           main] org.hibernate.tool.hbm2ddl.SchemaUpdate  : HHH000102: Fetching database metadata
2014-04-01 11:29:49.428  INFO 22368 --- [           main] c.atomikos.jdbc.AbstractDataSourceBean   : AtomikosDataSoureBean 'xads1': getConnection ( null )...
2014-04-01 11:29:49.428  INFO 22368 --- [           main] c.atomikos.jdbc.AbstractDataSourceBean   : AtomikosDataSoureBean 'xads1': init...
2014-04-01 11:29:49.428  WARN 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: WARNING: transaction manager not running?
2014-04-01 11:29:49.428  INFO 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: calling getAutoCommit...
2014-04-01 11:29:49.429  WARN 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: WARNING: transaction manager not running?
2014-04-01 11:29:49.429  INFO 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: calling getMetaData...
2014-04-01 11:29:49.429  WARN 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: WARNING: transaction manager not running?
2014-04-01 11:29:49.430  WARN 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: WARNING: transaction manager not running?
2014-04-01 11:29:49.430  INFO 22368 --- [           main] c.atomikos.jdbc.AtomikosConnectionProxy  : atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@63f9f0f2: calling createStatement...
2014-04-01 11:29:49.431  INFO 22368 --- [           main] org.hibernate.tool.hbm2ddl.SchemaUpdate  : HHH000396: Updating schema
2014-04-01 11:29:49.446  INFO 22368 --- [           main] o.hibernate.tool.hbm2ddl.TableMetadata   : HHH000261: Table found: atomikos_1.customer
2014-04-01 11:29:49.446  INFO 22368 --- [           main] o.hibernate.tool.hbm2ddl.TableMetadata   : HHH000037: Columns: [id, age, name]
2014-04-01 11:29:49.446  INFO 22368 --- [           main] o.hibernate.tool.hbm2ddl.TableMetadata   : HHH000108: Foreign keys: []
2014-04-01 11:29:49.446  INFO 22368 --- [           main] o.hibernate.tool.hbm2ddl.TableMetadata   : HHH000126: Indexes: [primary]
2014-04-01 11:29:49.447  INFO 22368 --- [           main] org.hibernate.tool.hbm2ddl.SchemaUpdate  : HHH000232: Schema update complete

 Answers

4

I think the CMTTransaction in the stack trace is the clue: Hibernate thinks you are in a container. I also think it might work if you just remove the javax.persistence.transactionType=JTA property.

Thursday, November 24, 2022
 
kostas
 
4

You can do it using GenericGenerator like this :

 @Entity
public class Client {

    @Id
    @GenericGenerator(name = "client_id", strategy = "com.eframe.model.generator.ClientIdGenerator")
    @GeneratedValue(generator = "client_id")  
    @Column(name="client_id")
    private String clientId;
}

and the custom generator class (will add prefix to the ID, you can make it do what you like):

public class ClientIdGenerator implements IdentifierGenerator {

@Override
public Serializable generate(SessionImplementor session, Object object)
        throws HibernateException {

    String prefix = "cli";
    Connection connection = session.connection();

    try {
        Statement statement=connection.createStatement();

        ResultSet rs=statement.executeQuery("select count(client_id) as Id from Client");

        if(rs.next())
        {
            int id=rs.getInt(1)+101;
            String generatedId = prefix + new Integer(id).toString();
            return generatedId;
        }
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return null;
}
}
Friday, August 26, 2022
 
lba
 
lba
5

If I understood you properly, you want to serialize only when the lazy loaded collection is fetched, but you don't want the serialization to trigger the fetching.

If that is the case you should use the jackson-datatype-hibernate, and added as their docs already explains

public class HibernateAwareObjectMapper extends ObjectMapper {

    public HibernateAwareObjectMapper() {
        registerModule(new Hibernate4Module());
    }
}

than register

 <mvc:annotation-driven>
        <mvc:message-converters>
            <!-- Use the HibernateAware mapper instead of the default -->
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="path.to.your.HibernateAwareObjectMapper" />
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

The module has a Feature.FORCE_LAZY_LOADING settings, that tells whether the object should be forced to be loaded and then serialized, which is by default set to false which I believe is the behaviour you need

Wednesday, December 21, 2022
 
meena
 
3

This will not work. You could use an SQLConstructorExpression however the returned instances would be unmanaged which is a major drawback.

An better option is to create a simple DB view which holds the pieces of summary info for the Project. You can them map the Project entity to both it's table and the associated summary view using the @SecondaryTable functionality of JPA.

https://en.wikibooks.org/wiki/Java_Persistence/Tables#Example_mapping_annotations_for_an_entity_with_multiple_tables

An added benefit is that you can sort and query on the summary values as for any other property.

Updated mapping:

@Entity
@Table(name = "projects")
@SecondaryTable(name = "projects_summary_vw")
public class Project{

   //use Integer rather than int to avoid issue outlined here:
   //http://.com/a/37160701/1356423

    @Column(name  = "parts", table = "projects_summary_vw", 
          insertable="false", updateable="false")
    private Integer partsCount;

    @Column(name  = "requests", table = "requestsCount" 
          insertable="false", updateable="false")
    private Integer requestsCount;

    //other mappings as required
}

No Custom query required:

@RepositoryRestResource(collectionResourceRel="projects", 
        path="projects")
interface ProjectRepository extends BaseRepository<Project, Long>, 
        ProjectRepositoryCustom {

}

An alternative non-JPA compliant solution may be to use some vendor specific extension rather than a view. Hibernate for example has an @Formula annotation which could be used:

https://docs.jboss.org/hibernate/orm/5.1/javadocs/org/hibernate/annotations/Formula.html

@Entity
@Table(name = "projects")
public class Project{

    @Formula("my count query as native sql")
    private Integer partsCount;

    @Formula("my count query as native sql")
    private Integer requestsCount;

    //other mappings as required
}
Thursday, September 8, 2022
2

How did you try ComponentScan? The issue here seems that you have a package structure like this:

tr.kasim.Application
  - Application.java
tr.kasim.Service
  - PersonelService.java
  - PersonelServiceImpl.java
tr.kasim.Dao
 - PersonelDao.java

Now since, the mainClass is in tr.kasim.Application it would scan for bean definitions inside that package (or a sub-package in tr.kasim.Application). So,

  • either you move the mainClass out to a parent-package like tr.kasim, or

  • use @ComponentScan({ "tr.kasim.Dao", "tr.kasim.Service", "tr.kasim.Application" }) and so on.

-- Update --

Based on the discussion so far, I'd suggest taking the first option as that reduces the effort to manually enable scan for entity, repository, etc.

Monday, October 3, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :