#StackBounty: #hibernate #lock-screen #luks #cryptsetup Lock on "suspend", but do not lock on "suspend to swap" (hi…

Bounty: 50

I enabled "lock on suspend" (sleep). This works fine, however this will also trigger when I hibernate the laptop. When I resume from hibernation, I have to enter two passwords: On the cryptsetup screen to unlock the drive and on the login screen.

Is there a way to not lock on hibernate (systemctl hibernate), but still lock on sleep?


I am on Ubuntu 20.04 (but I am flexible and will switch to any version, if that solves this problem).


Get this bounty!!!

#StackBounty: #sudo #gnome-shell #hibernate How to hibernate from Gnome Shell Extension without password?

Bounty: 50

On my system (Ubuntu 20.04) I have installed this Gnome Shell Extension that modifies the style of the power-off options and also adds an option to hibernate, which I occasionally use on my system in place of suspend. While the extension works as expected, every time I want to hibernate, I am prompted for a superuser password in order to proceed, which is annoying. To get rid of the password dialog, I followed this answer and added

my_username ALL=(ALL:ALL) NOPASSWD:/bin/systemctl hibernate

to my sudoers. After this change, I am able to hibernate from command line without password, as expected. However, the corresponding option from said Gnome Shell Extension still prompts me for a password. The code behind the scenes of the extension can be found here. I was unable to find any implementation of the function Util.trySpawnCommandLine, but it appears that it would just call the supplemented command in a shell. Hence, it’s not clear to me, why I am still asked for a password. I have checked that which systemctl returns /bin/systemctl. Could it be that commands from the Gnome Shell are executed in a different user context than the logged in user?

PS: Is it considered safe from a security standpoint, anyway, to add above line to the sudoers file?


Get this bounty!!!

#StackBounty: #mongodb #hibernate #grails Custom Id Generator for MongoDB not working

Bounty: 50

I have a domain class called Person, for which I’d like to customize the way ID’s are generated. If have a parameter called "fileId" and if this has a value, I want to generate the ID from this, otherwise it should generate a custom ObjectId.

From other threads I’ve seen that it should be possible to create a custom generator by creating a class that implements IdentifierGenerator and override the generate() method. Then in the mapping closure, I specify id generator: "<generator class>", but this doesn’t seem to do anything. I have tried setting breakpoints in the generate() method, but they are never reached. Instead, it seems like grails is instead ignoring my Generator and is using the default method.

I’m using grails version 4.0.10.

My Person class and CustomIdGenerator are defined below:

package hegardt.backend.grails

import grails.mongodb.MongoEntity
import grails.validation.Validateable
import hegardt.backend.grails.enums.Sex
import hegardt.backend.grails.helpers.FormatHelper
import hegardt.backend.grails.helpers.MongoHelper
import hegardt.backend.grails.model.person.LifeMilestone
import hegardt.backend.grails.model.person.Occupation
import hegardt.backend.grails.model.person.Schema
import hegardt.backend.grails.model.person.Spouse
import org.bson.types.ObjectId

import java.time.LocalDateTime

class Person implements MongoEntity<Person>, Schema {

    ObjectId id

    LocalDateTime dateCreated
    LocalDateTime lastUpdated

    String firstName
    List<String> middleNames = []
    String lastName
    Normalized normalized = new Normalized()
    Sex sex = Sex.UNKNOWN
    LifeMilestone birth
    LifeMilestone death
    LifeMilestone burial
    List<Occupation> occupations = []
    String notes
    String fileId
    List<Spouse> spouses = []
    ObjectId father
    ObjectId mother
    List<ObjectId> children = []
    List<String> references = []

    static mapping = {
        id generator: "hegardt.backend.grails.utils.CustomIdGenerator"
        autoTimestamp true
        collection "persons_test"
        database "hegardt"
    }

    static embedded = ['normalized', 'birth', 'death', 'burial', 'occupations', 'spouses']

    static constraints = {
        dateCreated nullable: true
        lastUpdated nullable: true
        firstName nullable: true, blank: false
        middleNames nullable: false, validator: { List<String> val ->
            return noNullValuesInList(val)
        }
        lastName nullable: true, blank: false
        normalized nullable: false, validator: { Normalized val ->
            val.validate()
        }
        sex nullable: false
        birth nullable: true, validator: { LifeMilestone val -> validateNested(val) }
        death nullable: true, validator: { LifeMilestone val -> validateNested(val) }
        burial nullable: true, validator: { LifeMilestone val -> validateNested(val) }
        occupations nullable: false, validator: { List<Occupation> vals ->
            validateNestedList(vals as List<Validateable>)
        }
        notes nullable: true, maxSize: 10000
        fileId nullable: true, blank: false, maxSize: 10, validator: { String val -> val?.isNumber() }
        spouses nullable: false, validator: { List<Spouse> val ->
            return val.every { Spouse s -> s.validate() } && validateUniqueIds(val.collect { Spouse s -> s.id })
        }
        father nullable: true       // TODO Validation by lookup in database
        mother nullable: true       // TODO Validation by lookup in database
        children nullable: false, validator: { List<ObjectId> val ->
            validateUniqueIds(val)
        }
        references nullable: false
    }

    // ------------------------------------------
    // --------------- Getters ------------------
    // ------------------------------------------

    // ... lots of getters ...

    // ------------------------------------------
    // --------------- Events -------------------
    // ------------------------------------------

    def beforeInsert() {
        doBeforeUpdateOrInsert()
        return true
    }

    def beforeUpdate() {
        doBeforeUpdateOrInsert()
    }

    def afterDelete() {
        // 1. Remove this person from parent's children
        Person father = getFatherObject()
        Person mother = getMotherObject()

        father?.children?.remove(id)
        mother?.children?.remove(id)
        father.save()
        mother.save()

        // 2. Remove this person as a parent from children
        List<Person> children = getChildObjects()

        children?.each {
            if (it.father == id) {
                it.father = null
            } else if (it.mother == id) {
                it.mother = null
            }
            it.save()
        }
    }

    private void doBeforeUpdateOrInsert() {
        // Calculate and set normalized fields
        normalized.fullName = FormatHelper.normalizeQueryString(getFullName())

        // Trigger generation of dates
        birth?.generateDate()
        death?.generateDate()
        burial?.generateDate()
        occupations?.each { it.generateDate() }
        spouses?.each { it.generateDate() }

        // Initially, I tried doing this, but the id was simply overwritten with a generated id
        if (fileId) {
            id = MongoHelper.toObjectId(fileId)
        }

        updateReferencedDocuments()
    }

    /**
     * Performs important postprocessing to a Person before it is added to the database. Should be called 'beforeUpdate' and 'beforeInsert'.
     *
     * Adds this person as a parent to all its children as well as a child to this person's parents. For this to work, the person has to have a set gender,
     * otherwise we can not know if it is the mother or the father of its children. Throws an error if it is not set (and has children and is not added already).
     */
    private void updateReferencedDocuments() {
        // 1. Set this person as father/mother of all of its children
        for (Person child in getChildObjects()) {

            if (!(child.father == id) || !(child.mother == id)) { // Not already set
                if (sex == Sex.MAN) {
                    child.father = id
                } else if (sex == Sex.WOMAN) {
                    child.mother = id
                } else {
                    log.error("Person with id ${id} has children specified, but is missing 'sex'.")
                }
            }
            child.save()
        }

        // 2. Set this person as a child to its parents
        Person mother = getMotherObject()
        Person father = getFatherObject()

        if (father && !father.children?.contains(id)) {
            father.children.add(id)
            father.save()
        }
        if (mother && !mother.children?.contains(id)) {
            mother.children.add(id)
            mother.save()
        }
    }
}

class Normalized implements Validateable {
    String fullName

    static constraints = {
        fullName nullable: true, validator: { String val ->
            if (val != null) FormatHelper.isQueryNormalized(val)
        }
    }

}
package hegardt.backend.grails.utils

import org.bson.types.ObjectId
import org.hibernate.HibernateException
import org.hibernate.engine.spi.SharedSessionContractImplementor
import org.hibernate.id.IdentifierGenerator

class CustomIdGenerator implements IdentifierGenerator {

    @Override
    Object generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
        println("GENERATING YOOOOOOOO")  // is never printed and breakpoint is never reached
        return new ObjectId()
    }
}


Get this bounty!!!

#StackBounty: #20.04 #suspend #hibernate Ubuntu Focal freezes and does not resume after suspend (e.g. laptop close)

Bounty: 50

When I close my laptop and re-open it (or it auto sleeps after inactivity), the machine will not resume correctly. The screen will show the sleep screen — a brief description of the suspend activity — and the fans will start blowing like a 747 taking off. The only recourse is to hard-boot (hold power button for 4 seconds).

This used to work OK with Bionic (which became unstable after too many experiments with various hardware hacking), so I’m a bit baffled.

There is a reference in dmesg to hibernation:

[   30.198017] Lockdown: systemd-logind: hibernation is restricted; see man kernel_lockdown.7

But it’s not clear to me how to resolve this issue. man kernel_lockdown discusses the disabled "unencrypted" hibernation, which implies an encrypted hibernation is possible, but does not provide further detail.

Ubuntu docs on Enable Hibernate With Encrypted Swap does supply some instructions, but does not seem to work. This implies that lvm must be in use, which in my case it is not (I opted for the zfs root directory during install, which does not use lvm).

I thought for a while this was related to the nvidia drivers (currently 460) not resuming state correctly, but I’ve tried all the settings (including forcing the intel chipset) with no change.

The syslog output from just before reboot is as follows. I don’t think I see anything interesting here, but I might not know what to look for.

Jul 25 12:04:49 xenon wpa_supplicant[2208]: nl80211: deinit ifname=p2p-dev-wlp4s0 disabled_11b_rates=0
Jul 25 12:04:49 xenon systemd-sleep[165210]: Suspending system...
Jul 25 12:04:49 xenon kernel: [ 3360.130627] PM: suspend entry (deep)
Jul 25 12:04:49 xenon wpa_supplicant[2208]: nl80211: deinit ifname=wlp4s0 disabled_11b_rates=0
Jul 25 12:04:51 xenon gnome-shell[17784]: [17775:17977:0725/120451.785183:ERROR:connection_factory_impl.cc(429)] Failed to connect to MCS endpoint with error -106
Jul 25 12:04:54 xenon kernel: [ 3364.649231] Filesystems sync: 4.519 seconds
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (**) Option "fd" "44"
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) event3  - Power Button: device removed
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (**) Option "fd" "47"
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) event6  - Video Bus: device removed
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (**) Option "fd" "48"
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) event7  - Video Bus: device removed
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (**) Option "fd" "49"
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) event0  - Power Button: device removed
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (**) Option "fd" "50"
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) event1  - Sleep Button: device removed
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (**) Option "fd" "51"
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) event8  - Chicony USB 2.0 Camera: Chicony: device removed
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (**) Option "fd" "52"
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) event4  - AT Translated Set 2 keyboard: device removed
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (**) Option "fd" "53"
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) event5  - SynPS/2 Synaptics TouchPad: device removed
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) systemd-logind: got pause for 13:69
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) systemd-logind: got pause for 13:64
Jul 25 12:04:54 xenon kernel: [ 3364.965699] rfkill: input handler enabled
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) systemd-logind: got pause for 13:71
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) systemd-logind: got pause for 226:0
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) systemd-logind: got pause for 13:68
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) systemd-logind: got pause for 13:65
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) systemd-logind: got pause for 13:70
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) systemd-logind: got pause for 13:67
Jul 25 12:04:54 xenon /usr/lib/gdm3/gdm-x-session[3482]: (II) systemd-logind: got pause for 13:72

What have I not checked?


Get this bounty!!!

#StackBounty: #java #hibernate #jpa #spring-data-jpa How to filter association entities across a mapping table using Spring Data JPA(Hi…

Bounty: 50

Is there a way to filter a soft deleted many-to-many association using @OneToMany and @ManyToOne, across an intermediate entity(mapping table)?

product and product_option_group are in N:M relation. I’m implementing the soft deletion using the disabled_datetime column and want to filter a collection of product_option_group from the product entity. This post is using @ManyToMany and @Where to achieve this. I followed and it worked(disabled product_option_groups are filtered). Note @Where(clause = "disabled_datetime is null") on ProductOptionGroup class.

// `product` <-> `product-product_option_group` <-> `product_option_group`

@Entity
@Table(name = "product")
public class Product implements Serializable {
    ...

    @ManyToMany
    @JoinTable(name = "product-product_option_group",
            joinColumns = @JoinColumn(name = "product_id"),
            inverseJoinColumns = @JoinColumn(name = "product_option_group_id"))
    private final Set<ProductOptionGroup> productOptionGroups = new HashSet<>();

    ...
}

@Entity
@Table(name = "product_option_group")
@Where(clause = "disabled_datetime is null")
public class ProductOptionGroup implements Serializable {
    ...

    @Column(name = "disabled_datetime")
    private ZonedDateTime disabledDatetime;

    ...
}

but I want to use @OneToMany towards the product-product_option_group table, like this.

@Entity
@Table(name = "product")
public class Product implements Serializable {
    ...

    @OneToMany(mappedBy = "id.product")
    private final Set<ProductProductOptionGroup> productProductOptionGroups = new HashSet<>();

    ...
}

@Entity
@Table(name = "`product-product_option_group`")
public class ProductProductOptionGroup implements Serializable {
    @EmbeddedId
    private final ProductProductOptionGroupId id = new ProductProductOptionGroupId();

    ...
}

@Embeddable
public class ProductProductOptionGroupId implements Serializable {
    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "product_id", referencedColumnName = "id")
    private Product product;

    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "product_option_group_id", referencedColumnName = "id")
    @Where(clause = "disabled_datetime is null")
    private ProductOptionGroup productOptionGroup;
}

@Entity
@Table(name = "product_option_group")
@Where(clause = "disabled_datetime is null")
public class ProductOptionGroup implements Serializable {
    ...
}

But then the @Where annotations won’t work anymore, so disabled ProductOptionGroups are also selected. How to solve this?


Get this bounty!!!

#StackBounty: #java #spring-boot #hibernate #jpa How to implement @ManyToMany with unique constraint?

Bounty: 50

I’d like to model npm package versions and their maintainers. Have a look at the following API response.

https://registry.npmjs.org/react

The package react with version 17.0.2 has multiple maintainers.

    "maintainers": [
        {
            "name": "sebmarkbage",
            "email": "sebastian@calyptus.eu"
        },
        {
            "name": "gaearon",
            "email": "dan.abramov@gmail.com"
        },
        {
            "name": "acdlite",
            "email": "npm@andrewclark.io"
        },
        {
            "name": "brianvaughn",
            "email": "briandavidvaughn@gmail.com"
        },
        {
            "name": "fb",
            "email": "opensource+npm@fb.com"
        },
        {
            "name": "trueadm",
            "email": "dg@domgan.com"
        },
        {
            "name": "sophiebits",
            "email": "npm@sophiebits.com"
        },
        {
            "name": "lunaruan",
            "email": "lunaris.ruan@gmail.com"
        }
    ],

A maintainer can have multiple packages, e.g. gaearon can also be the maintainer of another package.

Here is how I’m currently doing it. This my NpmPackageVersion.java.

@Entity
public class NpmPackageVersion {

  public NpmPackageVersion() {}

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
  @JsonManagedReference
  private Set<Maintainer> maintainers = new HashSet<>();

  public void addMaintainer(Maintainer maintainer) {
    this.maintainers.add(maintainer);
    maintainer.getNpmPackageVersions().add(this);
  }

  public void removeMaintainer(Maintainer maintainer) {
    this.maintainers.remove(maintainer);
    maintainer.getNpmPackageVersions().remove(this);
  }
}

Here is my Maintainer.java.

@Entity
public class Maintainer {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer id;

  @ManyToMany(fetch = FetchType.LAZY, mappedBy = "maintainers")
  @JsonBackReference
  private Set<NpmPackageVersion> npmPackageVersions = new HashSet<>();

  private String name;

  private String email;

  private String url;
}

Here are my database tables.

CREATE TABLE IF NOT EXISTS npm_package_version (
    id BIGSERIAL PRIMARY KEY,
    version TEXT NOT NULL
)

CREATE TABLE IF NOT EXISTS maintainer (
    id SERIAL PRIMARY KEY,
    name TEXT,
    email TEXT UNIQUE,
    url TEXT
)

CREATE TABLE IF NOT EXISTS npm_package_version_maintainers (
    npm_package_versions_id BIGINT NOT NULL REFERENCES npm_package_version,
    maintainers_id INT NOT NULL REFERENCES maintainer
)

As you can see I have a unique constraint for the maintainer email.

I’m now querying the npm registry and trying to store data in my database.

// do the http request and use a DTO, then create a new entity
var npmPackageVersion = new NpmPackageVersion();
npmPackageVersion.setVersion(version);
// add maintainers
if (value.maintainers() != null) {
  value
  .maintainers()
  .forEach(m -> {
    var maintainer = maintainerRepository.findByEmailIgnoreCase(m.email()).orElseGet(() -> {
      var inner = new Maintainer();
      inner.setEmail(m.email());
      inner.setName(m.name());
      inner.setUrl(m.url());
      return inner;
    });
    npmPackageVersion.addMaintainer(maintainer);
  });
}

// then save the new version

I’m checking if a maintainer is already in the database by using the email field from the API response. If the maintainer is already present I use it and if not I a create a new one. I associate every maintainer with the package.

When I’m trying to save the package I’m getting the following error

Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "maintainer_email_key"

I think I know why I’m getting this error. Java saves the new npm package version and at the same times tries to save all maintainers. If an already existing maintainer is part of the maintainers Set Postgres throws the error.

So my question is:
How can I prevent this error? How can I tell hiberante to only save NEW maintainers and for EXISTING maintainers only add the association to the npm_package_version_maintainers table? I should not try to save an existing maintainer again to the database.


Edit 2021/06/14

I’ve created a demo repo to reproduce my problem.

https://github.com/zemirco/hibernate-issue

Although I added hashCode and equals to all my entities I’m still getting the same error. I think we’re close but I’m still missing something. The relation is

Package -> Version -> Maintainer

So for every package has multiple versions. Every version has multiple maintainers. The same maintainer can be in multiple versions. So in the end when I try to save the Package Hibernate tries to save all versions and all maintainers. Then I’m getting the error that a maintainer might already exist in the database.


Get this bounty!!!

#StackBounty: #java #spring #spring-boot #hibernate Cannot create inner beanof type org.springframework.orm.jpa.SharedEntityManagerCrea…

Bounty: 50

I have deployed multitenant Spring boot application on AWS EC2. the code just works fine in the local system, but application is failing with below error after docker run in aws ec2.

] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'orderReportListener' defined in URL [jar:file:/app-service.jar!/BOOT-INF/classes!/com/aic/autofluence/appservice/scheduler/kafkaReportListener/OrderReportListener.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'reportFactoryImplData' defined in URL [jar:file:/app-service.jar!/BOOT-INF/classes!/com/aic/autofluence/appservice/scheduler/service/Impl/ReportFactoryImplData.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderReportRepository' defined in com.aic.autofluence.appservice.scheduler.repository.OrderReportRepository defined in @EnableJpaRepositories declared on TenantDatabaseConfig: Cannot create inner bean '(inner bean)#4293e066' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#4293e066': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
2021-05-10 18:58:57.081  INFO 1 --- [           main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'masterdb-persistence-unit'
2021-05-10 18:58:57.082  INFO 1 --- [           main] com.zaxxer.hikari.HikariDataSource       : masterdb-connection-pool - Shutdown initiated...
2021-05-10 18:58:57.099  INFO 1 --- [           main] com.zaxxer.hikari.HikariDataSource       : masterdb-connection-pool - Shutdown completed.
2021-05-10 18:58:57.103  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2021-05-10 18:58:57.124  INFO 1 --- [           main] ConditionEvaluationReportLoggingListener :

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-05-10 18:58:57.147 ERROR 1 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   :

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in com.aic.autofluence.appservice.scheduler.service.Impl.ReportFactoryImplData required a bean named 'entityManagerFactory' that could not be found.

Sample code I have as below:

tenantConfig: The EntityManagerFactory bean itself is not recognised. it is working good in local system, failing same in vm

@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = { "x.x.x.x.scheduler.repository", "x.x.x.x.scheduler.model" })
@EnableJpaRepositories(basePackages = {"x.x.x.x..scheduler.repository", "x.x.x.x..scheduler.service"},
        entityManagerFactoryRef = "tenantEntityManagerFactory",
        transactionManagerRef = "tenantTransactionManager")
public class TenantDatabaseConfig {

   @Bean(name = "tenantJpaVendorAdapter")
    public JpaVendorAdapter jpaVendorAdapter() {
        return new HibernateJpaVendorAdapter ();
    }

    @Bean(name = "tenantTransactionManager")
    public JpaTransactionManager transactionManager(@Qualifier("tenantEntityManagerFactory") EntityManagerFactory tenantEntityManager) {
        JpaTransactionManager transactionManager = new JpaTransactionManager ();
        transactionManager.setEntityManagerFactory(tenantEntityManager);
        return transactionManager;
    }
    
    @Bean(name = "datasourceBasedMultitenantConnectionProvider")
    @ConditionalOnBean(name = "masterEntityManagerFactory")
    public MultiTenantConnectionProvider multiTenantConnectionProvider() {
        return new DataSourceBasedMultiTenantConnectionProviderImpl();
    }

    @Bean(name = "currentTenantIdentifierResolver")
    public CurrentTenantIdentifierResolver currentTenantIdentifierResolver() {
        return new CurrentTenantIdentifierResolverImpl();
    }

    
    @Bean(name = "tenantEntityManagerFactory")
    @ConditionalOnBean(name = "datasourceBasedMultitenantConnectionProvider")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            @Qualifier("datasourceBasedMultitenantConnectionProvider")
                    MultiTenantConnectionProvider connectionProvider,
            @Qualifier("currentTenantIdentifierResolver")
                    CurrentTenantIdentifierResolver tenantResolver) {
        LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean ();
        //All tenant related entities, repositories and service classes must be scanned
        emfBean.setPackagesToScan("com.aic.autofluence.appservice");
        emfBean.setJpaVendorAdapter(jpaVendorAdapter());
        emfBean.setPersistenceUnitName("tenantdb-persistence-unit");
        Map<String, Object> properties = new HashMap<>();
        properties.put( Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
        properties.put( Environment.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider);
        properties.put( Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver);
        properties.put( Environment.DIALECT, "org.hibernate.dialect.MySQL5Dialect");
        properties.put( Environment.SHOW_SQL, true);
        properties.put( Environment.FORMAT_SQL, true);
        properties.put( Environment.HBM2DDL_AUTO, "none");
        emfBean.setJpaPropertyMap(properties);
        return emfBean;
    }
}


**MasterConfig: It is configured properly working fine**

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = {"x.x.x.x.mastertenant.model",
        "x.x.x.x.mastertenant.repository"
},
        entityManagerFactoryRef = "masterEntityManagerFactory",
        transactionManagerRef = "masterTransactionManager")
public class MasterDatabaseConfig {

    private static final Logger LOG = LoggerFactory.getLogger(MasterDatabaseConfig.class);

    @Autowired
    private MasterDatabaseConfigProperties masterDbProperties;

    @Bean(name = "masterDataSource")
    public DataSource masterDataSource() {
        HikariDataSource hikariDataSource = new HikariDataSource ();
        hikariDataSource.setUsername(masterDbProperties.getUsername());
        hikariDataSource.setPassword(masterDbProperties.getPassword());
        hikariDataSource.setJdbcUrl(masterDbProperties.getUrl());
        hikariDataSource.setDriverClassName(masterDbProperties.getDriverClassName());
        hikariDataSource.setPoolName(masterDbProperties.getPoolName());
        // HikariCP settings
        hikariDataSource.setMaximumPoolSize(masterDbProperties.getMaxPoolSize());
        hikariDataSource.setMinimumIdle(masterDbProperties.getMinIdle());
        hikariDataSource.setConnectionTimeout(masterDbProperties.getConnectionTimeout());
        hikariDataSource.setIdleTimeout(masterDbProperties.getIdleTimeout());
        LOG.info("Setup of masterDataSource succeeded.");
        return hikariDataSource;
    }

    @Primary
    @Bean(name = "masterEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean masterEntityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean ();
        em.setDataSource(masterDataSource());
        em.setPackagesToScan(new String[]{x,x,x,x...});
        em.setPersistenceUnitName("masterdb-persistence-unit");
        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter ();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(hibernateProperties());
        LOG.info("Setup of masterEntityManagerFactory succeeded.");
        return em;
    }

    @Bean(name = "masterTransactionManager")
    public JpaTransactionManager masterTransactionManager(@Qualifier("masterEntityManagerFactory") EntityManagerFactory emf) {
        JpaTransactionManager transactionManager = new JpaTransactionManager ();
        transactionManager.setEntityManagerFactory(emf);
        return transactionManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor ();
    }


    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put(org.hibernate.cfg.Environment.DIALECT, "org.hibernate.dialect.MySQL5Dialect");
        properties.put(org.hibernate.cfg.Environment.SHOW_SQL, true);
        properties.put(org.hibernate.cfg.Environment.FORMAT_SQL, true);
        properties.put(org.hibernate.cfg.Environment.HBM2DDL_AUTO, "none");
        return properties;
    }

Any Idea what might be the issue?

Thanks


Get this bounty!!!

#StackBounty: #java #hibernate How to make Hibernate not to rollback when an exception occurs

Bounty: 100

The following SQL if run in MSSQL will insert the 1st and 3rd rows successfully:

BEGIN TRAN
INSERT ... -- valid data
INSERT ... -- invalid data (e.g. over column width)
INSERT ... -- valid data
COMMIT

Even though the second row fails within the transaction, you can still see the two rows with some valid data after the commit in the table.

However, when trying something similar in Hibernate, it rollbacks the whole transaction. Is there a way to tell Hibernate not to rollback on failed rows and commit the rest as same as how MSSQL does it?

e.g.

EntityTransaction transaction = em.getTransaction();
transaction.begin();
em.persist(new MyEntity("good"));
em.persist(new MyEntity("too long"));
em.persist(new MyEntity("good"));
transaction.commit();


Get this bounty!!!

#StackBounty: #java #spring #hibernate #spring-data-jpa #entity-model Field 'record_id' doesn't have a default value – Spri…

Bounty: 50

I’m working on adding a feature to an already developed spring boot web application. The primary entity that has child entities is a Record. It has a few columns/variables that I want to now be in its own, separate entity (CustomerOrder) and exist in a one-to-one relationship with the Record. To summarize:

Record {

-thing 1

-thing 2

-thing 3

}

is now becoming:

CustomerOrder {

-thing 1

-thing 2

-thing 3

}

Record { CustomerOrder }

I’m having some issues with what I’ve produced. Here is the CustomerOrder model’s relevant relationship data:

@Entity
@Table(name="customer_orders")
public class CustomerOrder {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    ... other columns

    @OneToOne(orphanRemoval = true, cascade = CascadeType.ALL, mappedBy="customerOrder", fetch = FetchType.EAGER)
    private Record record;


}

And then here is the Record model’s relevant data:

@Entity
@Table(name="records")
public class Record extends Auditable<String> implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    ... other columns

    @OneToOne
    @JoinColumn(name="customer_order_id", nullable = false, unique = true)
    private CustomerOrder customerOrder;
}

My issue exists when I try to POST a record, when a user tries creating one in the ui. Here is the POST method for a record:

    @PostMapping
    public ResponseEntity<?> saveRecord(@RequestBody Record recordBody, BindingResult result) {
        if(!result.hasErrors()) {
            if(recordBody.getHardwareItems().isEmpty()) {
                record = recordsService.save(recordBody);
            } else {
                // Save the record first, recordId is required on hardwareItems
                // TODO: investigate Spring Hibernate/JPA rules - is there a way to save parent before children to avoid a null recordId
                CustomerOrder customerOrder = recordBody.getCustomerOrder();
                recordBody.setCustomerOrder(new CustomerOrder());
                customerOrder.setRecord(record);
                customerOrder = customerOrdersService.save(customerOrder);
                record = recordsService.save(recordBody);
            }
        } else {
            return new ResponseEntity<>(result.getAllErrors(), HttpStatus.BAD_REQUEST);
        }
        // Return the location of the created resource
        uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{recordId}").buildAndExpand(record.getId()).toUri();
        return new ResponseEntity<>(uri, HttpStatus.CREATED);
    }

The error I receive is the following:

2021-02-19 02:35:50.989  WARN 31765 --- [nio-8080-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1364, SQLState: HY000
2021-02-19 02:35:50.989 ERROR 31765 --- [nio-8080-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper   : Field 'record_id' doesn't have a default value

This makes sense to me at least, since I’m trying to save the CustomerOrder object that depends on a Record object, which has yet to have been persisted. So, how do I go about changing up the order and/or creating and persisting a Record object so that I can then save the CustomerOrder object to it?

Also, I am using mysql and here is the migration script that I already have. Must I add something here for the customer_orders table?

-- Add a sample user
INSERT IGNORE INTO users (first_name, last_name, email, password, enabled, role)
VALUES ('Sample', 'User', 'sample@email.com', 'sample password', true, 'ROLE_ADMIN');

-- Customer Reference Values
INSERT IGNORE INTO customers (name) VALUES ('value1');
INSERT IGNORE INTO customers (name) VALUES ('value2');
INSERT IGNORE INTO customers (name) VALUES ('value3');
INSERT IGNORE INTO customers (name) VALUES ('value4');
INSERT IGNORE INTO customers (name) VALUES ('value5');
INSERT IGNORE INTO customers (name) VALUES ('value6');
INSERT IGNORE INTO customers (name) VALUES ('value7');
INSERT IGNORE INTO customers (name) VALUES ('value8');

Here is the mysql script for the Records table and CustomerOrders table:

-- -----------------------------------------------------
-- Table `myapp`.`records`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `myapp`.`records` (
  `id` BIGINT NOT NULL AUTO_INCREMENT,
  `customer_order_id` BIGINT NOT NULL,
  `record_id` BIGINT NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `UK_7m7wsqy68b7omkufvckoqv2hf` (`customer_order_id` ASC) VISIBLE,
  INDEX `FKta31a9q1llknlo2n0jw741987` (`customer_id` ASC) VISIBLE,
  CONSTRAINT `FK3q3clytyrx7s8edp9ok821j3`
    FOREIGN KEY (`customer_order_id`)
    REFERENCES `myapp`.`customer_orders` (`id`),
  CONSTRAINT `FKta31a9q1llknlo2n0jw741987`
    FOREIGN KEY (`customer_id`)
    REFERENCES `myapp`.`customers` (`id`))
ENGINE = InnoDB
AUTO_INCREMENT = 27
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;


-- -----------------------------------------------------
-- Table `myapp`.`customer_orders`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `myapp`.`customer_orders` (
  `id` BIGINT NOT NULL AUTO_INCREMENT,
  `record_id` BIGINT NOT NULL,
  `record_id_test` BIGINT NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `UK_ilew9pg8y4qnyhmjg38k1fev2` (`record_id_test` ASC) VISIBLE,
  INDEX `FK5rpb3u59bblj7h70wjr5mvb01` (`record_id` ASC) VISIBLE,
  CONSTRAINT `FK5rpb3u59bblj7h70wjr5mvb01`
    FOREIGN KEY (`record_id`)
    REFERENCES `myapp`.`records` (`id`),
  CONSTRAINT `FKk7a0g7djyhymr54ehoftkhyfw`
    FOREIGN KEY (`record_id_test`)
    REFERENCES `myapp`.`records` (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;


Get this bounty!!!

#StackBounty: #java #spring #spring-boot #hibernate #jpa List of entity inside a hibernate entity with @NamedNativeQueries

Bounty: 100

I have a situation where i get List of entity in hiberate, But inside the main entity i have another entity list. The entities that i use:

EmpListBean.java

@NamedNativeQueries({
 @NamedNativeQuery(
         name = "EmpList",
         //Actual query involves lot of joins
         query = " SELECT ID , NAME FROM EMPLOYEE WHERE EMP_ID=:EMPID"    
             ,resultClass = EmpListBean.class
         )
})

@Entity
public class EmpListBean {



@Column(name = "ID")
private int id;    

@Column(name = "NAME")
private String empName;

// This is the list i need to retreive
@ManyToOne
@Column(name="workList")   
private List<WorkListBean> workList;

//Getters & Setters

}

WorkListBean.java

@NamedNativeQueries({
 @NamedNativeQuery(
         name = "WorkListBeanList",
         query = " SELECT ID , NAME FROM Work_List WHERE EMP_ID=:EMPID"    
             ,resultClass = WorkListBean.class
         )
})

@Entity
public class WorkListBean {



@Column(name = "ID")
private int id;    

@Column(name = "NAME")
private String workName;

//Getters & Setters

}

The DAO Layer

Query query = session.getNamedQuery("EmpList");             
query.setParameter("EMPID", myObj.getEmpId());
List<EmpListBean> oEmpListBean = query.list();

When executing below DAO layer code I get the "workList" Object as empty , I know this can be achieved by iterating the EmpListBean separately and calling named query for WorkListBean separately , but since the data is huge it takes too much time when doing that way, So wanted to know if there is any way that we could fetch WorkListBean inside EmpList Bean. The two entities used here are only for reference , the actual query i use is complex and could not reveal in this forum and it involves lot of table joins, So kindly let me know how this can be possible in hibernate.


Get this bounty!!!