GVKun编程网logo

Could not obtain transaction-synchronized Session for current thread 解决方案(could not obtain connection to query metadata)

14

在本文中,我们将为您详细介绍Couldnotobtaintransaction-synchronizedSessionforcurrentthread解决方案的相关知识,并且为您解答关于couldno

在本文中,我们将为您详细介绍Could not obtain transaction-synchronized Session for current thread 解决方案的相关知识,并且为您解答关于could not obtain connection to query metadata的疑问,此外,我们还会提供一些关于@Transactional 与 synchronized 联合使用问题、c# – 为什么SynchronizationContext.Current为null?、Changes of user relationship in AD can''t be correctly synchronized to SCSM、concurrency - Avoid excessive synchronization的有用信息。

本文目录一览:

Could not obtain transaction-synchronized Session for current thread 解决方案(could not obtain connection to query metadata)

Could not obtain transaction-synchronized Session for current thread 解决方案(could not obtain connection to query metadata)

在SHH整合的时候遇到如下异常代码时:org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread   的解决方案是:

在web.xml添加如下代码

<filter>
	<filter-name>SpringOpenSessionInViewFilter</filter-name>
	<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>SpringOpenSessionInViewFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

即可解决。

 

亲测哦。。。。。。

@Transactional 与 synchronized 联合使用问题

@Transactional 与 synchronized 联合使用问题

使用 synchronized 为操作数据库方法加锁,避免并发操作,然而为方法外加上事务注解 @Transactional 则无法完全避免并发操作,原因如下:
synchronized 是针对 方法的锁 而 事务注解是 针对方法的环绕处理 即在方法运行前开启事务 方法结束后提交事务

    getTransaction();
    process();
    commitTransaction();
    process的锁并不能约束事务的方法 于是 出现了 其他线程获取锁的时候 事务还没提交的情况 产生并发问题
    

解决方法是 将事务的获取和提交方法手动写入 process 方法中 使其纳入process 锁的约束

@Autowired
private PlatformTransactionManager platformTransactionManager;
@Autowired
private TransactionDefinition transactionDefinition;

// 开启事务
TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
// do something.
// 提交事务
platformTransactionManager.commit(transaction);

c# – 为什么SynchronizationContext.Current为null?

c# – 为什么SynchronizationContext.Current为null?

错误:对象引用未设置为对象的实例.

下面的算法有效.
我尝试了,然后我将Winform项目删除到另一个目录,并且SynchronizationContext.Current为null.
为什么?

SynchronizationContext uiCtx = SynchronizationContext.Current;  

private void backgroundWorker1_DoWork(object sender,DoWorkEventArgs e)
{
    int[] makeSelfMoves = new int[4];

    lock (replay)
    {
        // count should be more than 2
        foreach (keyvaluePair<int,int[]> item in replay)
        {              
            makeSelfMoves = replay[item.Key];
            codeFile.Executeall(makeSelfMoves[0],makeSelfMoves[1],makeSelfMoves[2],makeSelfMoves[3]);

            // i get the error here. uictx is null
            uiCtx.Post(o =>
            {
                PrintPieces(codeFile.PieceState());
            },null);                               

            System.Threading.Thread.Sleep(1000);
        }
    }
}

解决方法

您的代码严格依赖于类的构造函数的运行时间和位置.在以下情况下,SynchronizationContext.Current将为null:

>在代码创建Form类的实例或在Main()中调用Application.Run()之前,您的类对象过早创建.当Current成员设置为WindowsFormsSynchronizationContext的实例时,该类知道如何使用消息循环封送调用.通过将对象实例化代码移动到主窗体构造函数来解决此问题.
>您的类对象是在主UI线程以外的任何线程上创建的.只有Winforms应用程序中的UI线程才能封送调用.通过使用以下语句向您的类添加构造函数来诊断:

Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);

还要将此行添加到Program.cs中的Main()方法中.如果“输出”窗口中的显示值不同,则无效.通过将对象实例化代码再次移动到主窗体构造函数来解决此问题,以便确保它在UI线程上运行.

Changes of user relationship in AD can''t be correctly synchronized to SCSM

Changes of user relationship in AD can''t be correctly synchronized to SCSM

The relationship of users might be not correctly updated if related users were once re-named in AD or have duplicate records in DB.

Cause 1 - Known Issue: a renamed user in AD will be treated as a new object in SCSM

Symptom

There are multiple records for the same user in BaseManagedEntity.

Analysis

There is a blog talking about this kind of behavior: https://blogs.technet.microsoft.com/manageabilityguys/2013/06/17/managing-username-changes-in-service-manager/

I did a test in my lab environment (SCSM 2012 R2). After I rename a user in AD and run AD connector, there will be two objects co-existing in the table [dbo].[ManagedEntity] for the user, and two relationships in the table [dbo].[Relationship].

For example, after I change my user name from "wendi" to "wendii", then to "wendie", there are 3 user objects and 3 relationships in the DB.

Relationship:

BaseManagedEntity:

Then I manually deleted "wendi" from DB, and changed the manager from "weiwen" to "Administrator" in AD. The relationship got updated for the newest object "wendie", but not for the old object "wendii". That resulted in two managers for the user "wendii"/"wendie", which is actually the same user in AD.

Resolution

Firstly remove the duplicated users from [dbo].[ManagedEntity].

  1. If you don’t want to lose the relationships associated with the old object, please use the script in the blog to move all relationships from old object to new object.

    Note: In the script there is a path pointing to SCSM PowerShell Module. You may need to alter it manually based on the real location.

  2. Remove the duplicate user object:

$oldADUser = "wendi"
Get-SCClassInstance -Class (Get-SCClass -Name "System.Domain.User") -Filter "UserName -eq $oldADUser | Remove-SCClassInstance

After confirming there is no duplicate user objects, please change the manager relationship in AD, then check if the relationship can be updated correctly by AD connector.

Cause 2 - Duplicate AD connector introduces duplicate user records

If there is only 1 record in BaseManagedEntity, but multiple records in [LFXSTG].[AD_User], it is probably from duplicate AD connectors.

We can check the data sources of the records in [LFXSTG].[AD_User]:

This query can give you information about all data sources (connectors):

Select * from LFX.Datasource

A sample output:

DataSourceId DataSourceName DataSourceAddress DisplayName
2 ADConnector.af492f92b2d04b4092d2f0c6108a4aff LDAP://DC=contoso,DC=com CONTOSO AD Connector
11 ADConnector.762fe647adc14c2daba1191291e6b37f LDAP://OU=AdminUsers,OU=Users,DC=contoso,DC=com CONTOSO AD Connector - Users
12 ADConnector.b93d4f78d799462280e841e228f5f921 LDAP://DC=contoso,DC=com CONTOSO AD Connector - Printers
13 ADConnector.d49f58ebf7b84c509c3426cde55c7cd5 LDAP://DC=contoso,DC=com CONTOSO AD Connector - Computers
14 ADConnector.e56e3f09b5614c5ea554e3d0c06c7da4 LDAP://DC=contoso,DC=com CONTOSO AD Connector - Groups
15 ADConnector.747d1f1f252f46a59634378686a32dbe LDAP://OU=SCSM,OU=Groups,DC=contoso,DC=com CONTOSO AD Connector - SCSM Groups

Resolution

Disable all duplicate connectors. After that, all users modified in the future could be correctly updated.

For those users which are already affected by the issue, we can follow below steps to process them.

  • Run this query in ServiceManager to get the users who have duplicate relationships with relationship isDeleted = 0, as well as the connectors that brought the relationships. (This query focuses on "manager" relationship)
Select distinct
u.DisplayName ''User Display Name'',
u.UserName_6AF77E23_669B_123F_B392_323C17097BBD ''User'', 
Manager.UserName_6AF77E23_669B_123F_B392_323C17097BBD ''Manager'', 
r.RelationshipId, 
r.IsDeleted ''Is Relationship Deleted'',
C.DisplayName ''Connector'',
BME.IsDeleted ''Is Connector Deleted'',
R.LastModified
from Relationship R
left join RelationshipType RT on R.RelationshipTypeId = RT.RelationshipTypeId
left join MT_System$Domain$User Manager on manager.BaseManagedEntityId = R.SourceEntityId
left join MT_System$Domain$User U on u.BaseManagedEntityId = r.TargetEntityId
inner join DiscoverySourceToRelationship DSTR on R.RelationshipId = DSTR.RelationshipId
Left join DiscoverySource DS on DS.DiscoverySourceId = DSTR.DiscoverySourceId
left join MT_Connector C on convert(nvarchar(256),DS.ConnectorId) = C.Id
Left join BaseManagedEntity BME on C.BaseManagedEntityId = BME.BaseManagedEntityId
where RelationshipTypeName like ''%System.UserManagesUser%'' and u.BaseManagedEntityId in
(
Select 
u.BaseManagedEntityId
from Relationship R
left join RelationshipType RT on R.RelationshipTypeId = RT.RelationshipTypeId
left join MT_System$Domain$User Manager on manager.BaseManagedEntityId = R.SourceEntityId
left join MT_System$Domain$User U on u.BaseManagedEntityId = r.TargetEntityId
where RelationshipTypeName like ''%System.UserManagesUser%'' and r.IsDeleted = 0
group by U.UserName_6AF77E23_669B_123F_B392_323C17097BBD, u.BaseManagedEntityId
Having count(u.UserName_6AF77E23_669B_123F_B392_323C17097BBD) > 1)
order by U.UserName_6AF77E23_669B_123F_B392_323C17097BBD
  • Use below steps to automate the removal of un-needed relationships whilst keeping the most current one.
    1. Copy the query result with headers and save as a .csv file.
    2. Remove the needed relationships from the .csv file.
    3. Use below PowerShell commands to remove the un-needed relationships.
# You may change the file path.
$listcsv = Import-Csv C:\Files\UnneededRelationships.csv

foreach($list in $listcsv)
{
    Get-screlationshipinstance -id $listcsv.RelationshipId | remove-screlationshipinstance
}

concurrency - Avoid excessive synchronization

concurrency - Avoid excessive synchronization

avoid excessive synchronization 避免过度使用synchronization

Here is an example,which implements an observable set wrapper.It allow clients to subscribe to notifications when elements are added to the set.this is the Observer pattern. for brevity`s, the class does not provide notifications when elements are removed from the set.

这有一个观察着封装的set,它允许客户端订阅添加元素的通知,为了简介,没有提供移出元素的通知。

Observers subscribe to notifications by invoking the addObserver method and unsubscribe by invoking the removeObserver method. In both cases, an instance of the callback interface is passed to the method.

观察者订阅调用addObserver,取消订阅调用removeObserver,两种操作的参数都回调接口。


import java.util.*;

/**
 * Created by why on 10/23/2016.
 */
public class ObservableSet0<E> extends HashSet<E> {
    public ObservableSet0(Set<E> set) {
        super(set);
    }

    private final List<SetObserver<E>> observers = new ArrayList<SetObserver<E>>();

    public void addObserver(SetObserver<E> observer) {
        synchronized (observers) {
            observers.add(observer);
        }
    }

    public boolean removeObserver(SetObserver<E> observer) {
        synchronized (observers) {
            return observers.remove(observer);
        }
    }

    private void notifyElementAdded(E element) {
        synchronized (observers) {
            for (SetObserver<E> observer : observers)
                observer.added(this, element);
        }
    }

    @Override
    public boolean add(E element) {
        boolean added = super.add(element);
        if (added)
            notifyElementAdded(element);
        return added;
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        boolean result = false;
        for (E element : c)
            result |= add(element); // calls notifyElementAdded
        return result;
    }

    public static void main(String[] args) {
        ObservableSet0<Integer> set = new ObservableSet0<Integer>(new HashSet<Integer>());
        set.addObserver(new SetObserver<Integer>() {
            public void added(ObservableSet0<Integer> s, Integer e) {
                System.out.println(e);
            }
        });
        for (int i = 0; i < 100; i++)
            set.add(i);
    }

    static class SetObserver<E> {
        public void added(ObservableSet0<E> es, E element) {
        }
    }
}

The result will print 0 through 99.Now let`s try something els.Suppose we replace the addObserver call with one that passes an observer that prints the Integer value that was added to the set and removes itself if the value is 23.

结果是打印0-99。我们试着做一些其他事,添加一个订阅者,打印数字,并在数字是23的时候移出自己。

import java.util.*;

/**
 * caes an  java.util.ConcurrentModificationException
 * Changing ArrayList to CopyOnWriteArrayList can solve this problem
 * <p>
 * Created by why on 10/23/2016.
 */
public class ObservableSet1<E> extends HashSet<E> {
    public ObservableSet1(Set<E> set) {
        super(set);
    }

    // fixme 2016-10-23 CopyOnWriteArrayList can solve this problem
    private final List<SetObserver<E>> observers = new ArrayList<SetObserver<E>>();

    public void addObserver(SetObserver<E> observer) {
        synchronized (observers) {
            observers.add(observer);
        }
    }

    public boolean removeObserver(SetObserver<E> observer) {
        synchronized (observers) {
            return observers.remove(observer);
        }
    }

    private void notifyElementAdded(E element) {
        synchronized (observers) {
            for (SetObserver<E> observer : observers)
                observer.added(this, element);
        }
    }

    @Override
    public boolean add(E element) {
        boolean added = super.add(element);
        if (added)
            notifyElementAdded(element);
        return added;
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        boolean result = false;
        for (E element : c)
            result |= add(element); // calls notifyElementAdded
        return result;
    }

    public static void main(String[] args) {
        ObservableSet1<Integer> set = new ObservableSet1<Integer>(new HashSet<Integer>());
        set.addObserver(new SetObserver<Integer>() {
            public void added(ObservableSet1<Integer> s, Integer e) {
                System.out.println(e);
                if (e == 23) {
                    set.removeObserver(this);
                }
            }
        });
        for (int i = 0; i < 100; i++)
            set.add(i);
    }

    static class SetObserver<E> {
        public void added(ObservableSet1<E> es, E element) {
        }
    }
}

You might expect the program to print the numbers 0 through 23.But you get an unexpected ConcurrentModificationException. The problem is that notifyElementAdded is in the process of iterating over the observers list when it invokes the observer`s added method.he iteration in the notifyElementAddded method is in a synchronized block to prevent concurrent modification, but is does not prevent the iterating thread itself from calling back into the observable set and modifying its observers list.

Now let`s try something odd:Write an observer that attempts to unsubscribe, but instead of calling removeObserver directly, it engages the services of another thread to do the deed.This observer uses an executor service.


import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * dead lock
 * <p>
 * This time we don’t get an exception; we get a deadlock. The background thread
 * calls s.removeObserver, which attempts to lock observers, but it can’t acquire
 * the lock, because the main thread already has the lock. All the while, the main
 * thread is waiting for the background thread to finish removing the observer, which
 * explains the deadlock.
 * Created by why on 10/23/2016.
 */
public class ObservableSet2<E> extends HashSet<E> {
    public ObservableSet2(Set<E> set) {
        super(set);
    }

    private final List<SetObserver<E>> observers = new ArrayList<SetObserver<E>>();

    public void addObserver(SetObserver<E> observer) {
        synchronized (observers) {
            observers.add(observer);
        }
    }

    public boolean removeObserver(SetObserver<E> observer) {
        synchronized (observers) {
            return observers.remove(observer);
        }
    }

    private void notifyElementAdded(E element) {
        synchronized (observers) {
            for (SetObserver<E> observer : observers)
                observer.added(this, element);
        }
    }

    @Override
    public boolean add(E element) {
        boolean added = super.add(element);
        if (added)
            notifyElementAdded(element);
        return added;
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        boolean result = false;
        for (E element : c)
            result |= add(element); // calls notifyElementAdded
        return result;
    }

    public static void main(String[] args) {
        ObservableSet2<Integer> set = new ObservableSet2<Integer>(new HashSet<Integer>());
        set.addObserver(new SetObserver<Integer>() {
            public void added(ObservableSet2<Integer> s, Integer e) {
                System.out.println(e);
                if (e == 23) {
                    ExecutorService executor =
                            Executors.newSingleThreadExecutor();
                    final SetObserver<Integer> observer = this;
                    try {
                        executor.submit(new Runnable() {
                            public void run() {
                                s.removeObserver(observer);
                            }
                        }).get();
                    } catch (ExecutionException ex) {
                        throw new AssertionError(ex.getCause());
                    } catch (InterruptedException ex) {
                        throw new AssertionError(ex.getCause());
                    } finally {
                        executor.shutdown();
                    }
                }
            }
        });
        for (int i = 0; i < 100; i++)
            set.add(i);
    }

    static class SetObserver<E> {
        public void added(ObservableSet2<E> es, E element) {
        }
    }
}

This time we don`t get an exception,we get a deadlock.The background thread calls s.removeObserve,which attempts to lock observers,bug it can not acquire the lock,because the main thread already has the lock.All the while,the main thread is waiting for the background thread to finish removing the observer,which explains the deadlock.

这是一个人为的例子,因为我们没有必要再观察者中时候线程池。

解决上面两种情况引起的问题,我们可以把方法调用移出同步块。就上面的例子,我们可以在notifyElementAdded方法中生产observer的快照,然后可以 安全的去掉锁。这样上面两个例子都会完美运行。

private void notifyElementAdded(E element) {
    List<SetObserver<E>> snapshot = null;
    synchronized(observers) {
        snapshot = new ArrayList<SetObserver<E>>(observers);
    }
    for (SetObserver<E> observer : snapshot)
        observer.added(this, element);
}

事实上有更好的方法,java 1.5提供的concurrent collection中的CopyOnWriteArrayList,就是为这个目的而生。当元素改变时,他会新复制一份 完整的数据,对其他情况而言这种操作可能非常粗暴,但是非常适合保存observer,因为他改变的情况比较少。

private final List<SetObserver<E>> observers = new CopyOnWriteArrayList<SetObserver<E>>();
public void addObserver(SetObserver<E> observer) {
    observers.add(observer);
}
public boolean removeObserver(SetObserver<E> observer) {
    return observers.remove(observer);
}
private void notifyElementAdded(E element) {
    for (SetObserver<E> observer : observers)
        observer.added(this, element);
}

所有的外部调用都在同步块之外,也就是开放式调用(open call)。除了避免故障的产生,还可以大大的提高并发。

在同步块中尽可能的少操作

如果需要进行大量操作,可以考虑把这些操作移出同步块。

![My helpful screenshot]({{ site.url }}/assets/screenshot.jpg)

关于Could not obtain transaction-synchronized Session for current thread 解决方案could not obtain connection to query metadata的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于@Transactional 与 synchronized 联合使用问题、c# – 为什么SynchronizationContext.Current为null?、Changes of user relationship in AD can''t be correctly synchronized to SCSM、concurrency - Avoid excessive synchronization等相关知识的信息别忘了在本站进行查找喔。

本文标签: